tag:blogger.com,1999:blog-49243222579889727312024-03-08T15:25:55.458+08:00蓮花淨土Unknownnoreply@blogger.comBlogger372125tag:blogger.com,1999:blog-4924322257988972731.post-60033924436977811012021-01-13T12:41:00.006+08:002021-01-14T08:55:38.622+08:00揮灑Python(73):基於 pytorch 之 y=wx+b 線性回歸(Linear Regression)<div style="background-color: #282c34; color: #bbbbbb; line-height: 20px; white-space: pre;"><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">import</span> torch</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">import</span> torch<span style="color: #abb2bf;">.</span>nn <span style="color: #e06c75;">as</span> nn </span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">import</span> matplotlib<span style="color: #abb2bf;">.</span>pyplot <span style="color: #e06c75;">as</span> plt </span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">from</span> torch<span style="color: #abb2bf;">.</span>autograd <span style="color: #e06c75;">import</span> Variable</span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ---------------------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">plt<span style="color: #abb2bf;">.</span>rcParams[<span style="color: #e5c07b;">"font.family"</span>] <span style="color: #e06c75;">=</span> <span style="color: #e5c07b;">"sans-serif"</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">plt<span style="color: #abb2bf;">.</span>rcParams[<span style="color: #e5c07b;">"font.sans-serif"</span>] <span style="color: #e06c75;">=</span> [<span style="color: #e5c07b;">"Microsoft JhengHei"</span>]</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">plt<span style="color: #abb2bf;">.</span>rcParams[<span style="color: #e5c07b;">'axes.unicode_minus'</span>] <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">False</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ---------------------------------------------------------------------</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># matplotlib 設定中文顯示字型及正常顯示座標軸之負號</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># --------------------------------------------------------------------- </span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">torch<span style="color: #abb2bf;">.</span>manual_seed(<span style="color: #c678dd;">15</span>)</span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ---------------------------------------------------------------------</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># torch.manual_seed(n):當設定 manual_seed(n) ,假若 n 值不變,則每次產生的</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 隨機亂數也會相同;反之,設定的 n 值不同,=> 產生的隨機亂數值也會不同。但若不設定</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># manual_seed(n) => 根據系統時間決定亂數種子值,故每次生成的隨機亂數也跟著不同。</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ---------------------------------------------------------------------</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"><div style="color: #bbbbbb; font-family: "Times New Roman"; font-size: medium;"><span style="font-family: Source Code Pro; font-size: x-small;">x <span style="color: #e06c75;">=</span> Variable(torch<span style="color: #abb2bf;">.T</span>ensor([i <span style="color: #e06c75;">for</span> i <span style="color: #e06c75;">in</span> <span style="color: #98c379;">range</span>(<span style="color: #c678dd;">0</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">15</span>)])<span style="color: #abb2bf;">.</span>reshape(<span style="color: #c678dd;">15</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">1</span>))</span></div><div style="color: #bbbbbb; font-family: "Times New Roman"; font-size: medium;"><span style="font-family: Source Code Pro; font-size: x-small;">y <span style="color: #e06c75;">=</span> Variable(torch<span style="color: #abb2bf;">.T</span>ensor([j<span style="color: #e06c75;">+</span>torch<span style="color: #abb2bf;">.</span>randint(<span style="color: #e06c75;">-</span><span style="color: #c678dd;">3</span><span style="color: #abb2bf;">,</span><span style="color: #c678dd;">4</span><span style="color: #abb2bf;">,</span>(<span style="color: #c678dd;">1</span><span style="color: #abb2bf;">,</span>)) <span style="color: #e06c75;">for</span> j <span style="color: #e06c75;">in</span> x])<span style="color: #abb2bf;">.</span>reshape(<span style="color: #c678dd;">15</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">1</span>))</span></div></span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ---------------------------------------------------------------------</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># x, y 亦可為:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #848d9b;">#</span> x <span style="color: #e06c75;">=</span> Variable(torch<span style="color: #abb2bf;">.</span>tensor([i <span style="color: #e06c75;">for</span> i <span style="color: #e06c75;">in</span> <span style="color: #98c379;">range</span>(<span style="color: #c678dd;">0</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">15</span>)]<span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">dtype</span><span style="color: #e06c75;">=</span>torch<span style="color: #abb2bf;">.</span>float32)<span style="color: #abb2bf;">.</span>reshape(<span style="color: #c678dd;">15</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">1</span>))</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #848d9b;">#</span> y <span style="color: #e06c75;">=</span> Variable(torch<span style="color: #abb2bf;">.</span>tensor([j<span style="color: #e06c75;">+</span>torch<span style="color: #abb2bf;">.</span>randint(<span style="color: #e06c75;">-</span><span style="color: #c678dd;">3</span><span style="color: #abb2bf;">,</span><span style="color: #c678dd;">4</span><span style="color: #abb2bf;">,</span>(<span style="color: #c678dd;">1</span><span style="color: #abb2bf;">,</span>)) <span style="color: #e06c75;">for</span> j <span style="color: #e06c75;">in</span> x]<span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">dtype</span><span style="color: #e06c75;">=</span>torch<span style="color: #abb2bf;">.</span>float32)<span style="color: #abb2bf;">.</span>reshape(<span style="color: #c678dd;">15</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">1</span>))</span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ---------------------------------------------------------------------</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># x, y 數據利用 reshape(15, 1) 變形為 (15x1) 之二維矩陣</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># Tensor 通常翻譯成「張量」,實際操作上可視為 N 維的矩陣。附帶一提,編程設計裡頭,</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 向量(Vector) 通常代表㇐維陣列,而矩陣(Matrix) 則用來指稱二維或二維以上陣列。</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 詳見:https://pytorch.org/docs/1.7.1/tensors.html ,此為英文頁面,可以利用</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># google 瀏覽器翻譯成中文,方便檢視學習..</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ---------------------------------------------------------------------</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># pytorch 的 Tensor(張量) 類似 numpy.ndarray(多維陣列),且支持 GPU 並行計算。</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ↓↓↓</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ● 零維張量為純量</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># => Variable(torch.tensor(1.5, dtype=torch.float32)) </span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># => .shape=torch.Size([]) .dim()=0 => 純量 tensor(1.5000)</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ● 一維張量為向量(陣列)</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># => Variable(torch.tensor([1.5, 2.5], dtype=torch.float32)) </span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># => .shape=torch.Size([2]) .dim()=1 => 一維向量(陣列)</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ● 二維張量為矩陣</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># => Variable(torch.tensor([[1.5, 2.5], [3.5, 4.5]], dtype=torch.float32)</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># => .shape=torch.Size([2, 2]) .dim()=2 => 2x2 二維矩陣</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ● 三維或三維以上張量或稱多維張量</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># => Variable(torch.tensor([[[1.5000], [2.5000]],[[3.5000],[4.5000]],[[5.5000],[6.5000]]], </span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># dtype=torch.float32))</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># => .shape=torch.Size([3, 2, 1]) .dim()=3 => 3x2x1 三維張量</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ---------------------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">inputSize <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">1</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">outputSize <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">1</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">learningRate <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">0.001</span> <span style="color: #848d9b;"># 學習率,控制梯度下降「步距」大小</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">numEpochs <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">2000</span> <span style="color: #848d9b;"># 執行 2000 次訓練(也就是學習)</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ---------------------------------------------------------------------</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 全連接之線性層(fully connected linear layer) 的條件下:</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># x 為 (15x1) 的二維矩陣資料,可以理解為 15 筆的輸入資料,但這 15 是指批次(batch)</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 大小,而非單一筆資料大小,也就是所謂的 batch_size。這 batch_size 設定目的在於利</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 用矩陣運算達到優化速度的效果(通常像 numpy 或一些深度學習框架,對矩陣運算會特別優化</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 處理),至於 x 中單筆資料內容,卻僅僅是一個數值,在 nn.Linear 模型中的 inputSize</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 實指這單筆資料的 size 。本例 x 共有 x[0], x[1], x[2]..., x[14] 等 15 筆資料,</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 也就是 batch_size = 15,但每筆輸入資料的 size 卻為 1 (也就是單一個數值),因此這</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># inputSize = 1 而非 15。</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ----------------------------------------------------------------------</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 再舉個例子:</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># x = torch.tensor([[1.0, 2.0],</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># [3.0, 4.0],</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># [5.0, 6.0],</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># [7.0, 8.0],</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># [9.0, 10.0],</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># [11.0, 12.0]])</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># x 為 (6x2) 的矩陣,batch_size = 6 => inputSize = 2 (單筆輸入的資料長度)</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># </span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ---------------------------------------------------------------------</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 本例基於 y=wx+b 的線性回歸分析,因此,x, y 存在線性相依的關係,故 inputSize=1,</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 且 outputSize=1 。一個 x 值經過 y=wx+b,會映射出一個 y 值 (假設 w, b 為已知)</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 然而本範例卻是給予 15 個 (x,y) 樣本點,也就是訓練集資料,反求 w, b 最佳化值。換</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 言之,x, y 為已知平面座標上的離散點,但求 w, b 最佳化值以構建一線性方程式來整體逼</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 近 (x,y) 樣本點。最佳化過程就是訓練過程,也就是學習過程,使用手段就是梯度下降法。</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ---------------------------------------------------------------------</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;">#《inputSize 及 outputSize 解析》</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 原定義:torch.nn.Linear(in_features: int, out_features: int, bias: bool = True)</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 摘自:https://pytorch.org/docs/stable/generated/torch.nn.Linear.html</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># in_features – size of each input sample (注意,是每一個輸入樣本大小,不是批次大小)</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># out_features – size of each output sample (注意,是每一個輸出樣本大小,不是批次大小)</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># bias – If set to False, the layer will not learn an additive bias. Default: True</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># bias:如果 False,訓練過程不附加偏權值,預設值為 True</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;">#《參考文獻》</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># https://stackoverflow.com/questions/54916135/what-is-the-class-definition-of-nn-linear-in-pytorch</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># https://blog.csdn.net/qq_42079689/article/details/102873766?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># </span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ---------------------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #56b6c2;">class</span> <span style="color: #61afef;">Net</span>(<span style="color: #98c379;">nn</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">Module</span>): <span style="color: #848d9b;"># Net 繼承 nn.Module</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #56b6c2;">def</span> <span style="color: #98c379;">__init__</span>(<span style="color: #d19a66; font-style: italic;">self</span><span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">inputSize</span><span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">outputSize</span>): <span style="color: #848d9b;"># Net 建構式</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #56b6c2;">super</span>()<span style="color: #abb2bf;">.</span><span style="color: #98c379;">__init__</span>() <span style="color: #848d9b;"># 呼叫父類建構式</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>hidden <span style="color: #e06c75;">=</span> nn<span style="color: #abb2bf;">.</span>Linear(inputSize<span style="color: #abb2bf;">,</span> outputSize) </span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># 定義 Linear 層 hidden(名稱自訂) 源自 nn.Linear 類別</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> </span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #56b6c2;">def</span> <span style="color: #98c379;">forward</span>(<span style="color: #d19a66; font-style: italic;">self</span><span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">x</span>): <span style="color: #848d9b;"># 正向傳播</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> out <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>hidden(x) <span style="color: #848d9b;"># 經由 Linear 層產生輸出</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">return</span> out</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># ------------------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># forward 函數是如何被調用的呢?</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># 1. nn.Module 是所有神經網路的 Base Class </span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># https://pytorch.org/docs/stable/generated/torch.nn.Module.html</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># 2. pytorch 在 nn.Module 中實作了 __call__() 方法,而在 __call__() 方法</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># 中調用了 forward() 函數,這 __call__() 方法可以讓類別具體化之實例擁有類</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># 似函數的功能,故可直接被呼叫。</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># 參考:http://kailotus.blogspot.com/2020/11/python71call.html</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># 3. 後續 net(inputs) 相當 net.__call__(inputs) 相當 net.forward(inputs)</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># 但不直接使用 net.forward(inputs)</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># 4. forward() 為正向傳播,藉由輸入 x 訓練資料,取得預測 out 輸出值</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># 5. 上述 out 輸出值再與訓練資料集的 y 進行均方誤差 (Mean squared error) </span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># 計算,也就是損失函數計算 (見後:神經網路模型訓練)。</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># lossFunction = nn.MSELoss()</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># ....</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># loss = lossFunction(outputs, targets)</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># 6. 神經網路訓練目標在求最小的損失函數,也就是 loss 最小值,利用梯度下降法</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #848d9b;"># ------------------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> </span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">net <span style="color: #e06c75;">=</span> Net(inputSize<span style="color: #abb2bf;">,</span> outputSize) </span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">lossFunction <span style="color: #e06c75;">=</span> nn<span style="color: #abb2bf;">.</span>MSELoss()</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">optimizer <span style="color: #e06c75;">=</span> torch<span style="color: #abb2bf;">.</span>optim<span style="color: #abb2bf;">.</span>SGD(net<span style="color: #abb2bf;">.</span>parameters()<span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">lr</span><span style="color: #e06c75;">=</span>learningRate)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">inputs <span style="color: #e06c75;">=</span> x</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">targets <span style="color: #e06c75;">=</span> y</span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ----------------------------------------------------------------------</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 1. net = Net(inputSize, outputSize),net 是 Net 的一個實例,inputSize,</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># outputSize 兩個參數直接對應到建構式 __init__(self, inputSize, outputSize)</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 這 inputSize 係指單筆輸入資料之大小;outputSize 則指單筆輸出資料之大小。</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 《注意:這 inputSize, outputSize 非指 batch_size》</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 2. lossFunction = nn.MSELoss(),定義損失函數採均方誤差 MSE</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 3. optimizer = torch.optim.SGD(net.parameters(), lr=learningRate),定義</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 優化器,採隨機梯度下降法 (SGD, Stochastic Gradient Descent) 來對損失函數進</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 行優化處理,主要透過 SGD 來優化 w, b 參數,目標在求得最小損失函數</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 4. inputs = x,神經網路的輸入為訓練資料集的 x 樣本資料 (batch_size=15)</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 5. targets = y,神經網路擬合的目標為訓練資料集的 y 樣本資料 (batch_size=15)</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ----------------------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"</span><span style="color: #56b6c2;">\n</span><span style="color: #e5c07b;">神經網路模型訓練前參數值..."</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">for</span> name<span style="color: #abb2bf;">,</span> param <span style="color: #e06c75;">in</span> net<span style="color: #abb2bf;">.</span>named_parameters()<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">if</span> param<span style="color: #abb2bf;">.</span>requires_grad<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #98c379;">print</span>(name<span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">":"</span><span style="color: #abb2bf;">,</span> param<span style="color: #abb2bf;">.</span>data)</span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;">#</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"weight 權重之 shape:"</span><span style="color: #abb2bf;">,</span> net<span style="color: #abb2bf;">.</span>hidden<span style="color: #abb2bf;">.</span>weight<span style="color: #abb2bf;">.</span>data<span style="color: #abb2bf;">.</span>shape)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"bias 偏權值之 shape:"</span><span style="color: #abb2bf;">,</span> net<span style="color: #abb2bf;">.</span>hidden<span style="color: #abb2bf;">.</span>bias<span style="color: #abb2bf;">.</span>data<span style="color: #abb2bf;">.</span>shape)</span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ----------------------------------------------------------------------</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 輸出 weight 及 bias 的 shape:</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># weight 權重之維度: torch.Size([1, 1]) => 二維 1x1 矩陣</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># bias 偏權值之維度: torch.Size([1]) => 一維 單一元素陣列</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ----------------------------------------------------------------------</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 輸出 weight 及 bias 的 dimension(維度):</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># print(net.hidden.weight.data.dim()) => 輸出 weight dimension => 2</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># print(net.hidden.bias.data.dim()) => 輸出 bias dimension => 1</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># ----------------------------------------------------------------------</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 以下開始訓練神經網路模型...</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"</span><span style="color: #56b6c2;">\n</span><span style="color: #e5c07b;">神經網路模型訓練開始..."</span>)</span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;">#</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">for</span> i <span style="color: #e06c75;">in</span> <span style="color: #98c379;">range</span>(numEpochs)<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> optimizer<span style="color: #abb2bf;">.</span>zero_grad() </span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> outputs <span style="color: #e06c75;">=</span> net(inputs)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> loss <span style="color: #e06c75;">=</span> lossFunction(outputs<span style="color: #abb2bf;">,</span> targets)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> loss<span style="color: #abb2bf;">.</span>backward()</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> optimizer<span style="color: #abb2bf;">.</span>step()</span></div><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">if</span> (i<span style="color: #e06c75;">+</span><span style="color: #c678dd;">1</span>) <span style="color: #e06c75;">%</span> <span style="color: #c678dd;">5</span> <span style="color: #e06c75;">==</span> <span style="color: #c678dd;">0</span><span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #56b6c2;">f</span><span style="color: #e5c07b;">"</span><span style="color: #56b6c2;">{</span>i<span style="color: #56b6c2;">}</span><span style="color: #e5c07b;">/</span><span style="color: #56b6c2;">{</span>numEpochs<span style="color: #56b6c2;">}</span><span style="color: #e5c07b;"> => loss:</span><span style="color: #56b6c2;">{</span>loss<span style="color: #56b6c2;">}</span><span style="color: #e5c07b;">"</span>)</span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;">#</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"神經網路模型訓練結束..."</span>)</span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;">#</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 神經網路模型訓練結束...</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;">#</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># --------------------------------------------------------------------</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 1. optimizer.zero_grad(),梯度清空為 0,避免上一次梯度計算值與本次梯度值累加。</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 預設情況下梯度是累加的。經過迭代運算,會把上次梯度值累加至本次的梯度,因此在損失</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 函數值反向傳播更新參數梯度之前,先行將參數梯度清空為 0 。 </span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 2. outputs = net(inputs),將訓練資料集輸入 net 神經網路模型,並取得預測輸出</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 3. loss = lossFunction(outputs, targets),根據均方誤差 nn.MSELoss() 計</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 算損失函數,也就是將 net 網路模型之預測輸出值 outputs 與訓練集的 targets </span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 目標值進行均方誤差計算以產生損失函數值。</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 4. loss.backward(),將損失函數反向傳播以計算網路中參數的梯度。</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 5. optimizer.step(),進行優化,把梯度傳播到網路並更新參數。</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># --------------------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"</span><span style="color: #56b6c2;">\n</span><span style="color: #e5c07b;">神經網路模型訓練後參數值..."</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">for</span> name<span style="color: #abb2bf;">,</span> param <span style="color: #e06c75;">in</span> net<span style="color: #abb2bf;">.</span>named_parameters()<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">if</span> param<span style="color: #abb2bf;">.</span>requires_grad<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #98c379;">print</span>(name<span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">":"</span><span style="color: #abb2bf;">,</span> param<span style="color: #abb2bf;">.</span>data)</span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># --------------------------------------------------------------------</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;">#《輸出訓練模型之參數》</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 參考:https://discuss.pytorch.org/t/how-to-print-models-parameters-with-its-name-and-requires-grad-value/10778/2</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># --------------------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">predY <span style="color: #e06c75;">=</span> net(x) <span style="color: #848d9b;"># 將訓練資料集的 x 代入「已訓練好的」 net 模型並輸出預測值</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">plt<span style="color: #abb2bf;">.</span>figure(<span style="color: #d19a66; font-style: italic;">figsize</span><span style="color: #e06c75;">=</span>(<span style="color: #c678dd;">8</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">6</span>))</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">plt<span style="color: #abb2bf;">.</span>plot(x<span style="color: #abb2bf;">.</span>data<span style="color: #abb2bf;">.</span>numpy()<span style="color: #abb2bf;">,</span> y<span style="color: #abb2bf;">.</span>data<span style="color: #abb2bf;">.</span>numpy()<span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">"x"</span><span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">color</span><span style="color: #e06c75;">=</span><span style="color: #e5c07b;">"#006AFF"</span><span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">label</span><span style="color: #e06c75;">=</span><span style="color: #e5c07b;">"原始樣本"</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">plt<span style="color: #abb2bf;">.</span>plot(x<span style="color: #abb2bf;">.</span>data<span style="color: #abb2bf;">.</span>numpy()<span style="color: #abb2bf;">,</span> predY<span style="color: #abb2bf;">.</span>data<span style="color: #abb2bf;">.</span>numpy()<span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">color</span><span style="color: #e06c75;">=</span><span style="color: #e5c07b;">"#FF0077"</span><span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">label</span><span style="color: #e06c75;">=</span><span style="color: #e5c07b;">"迴歸線"</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">plt<span style="color: #abb2bf;">.</span>legend(<span style="color: #d19a66; font-style: italic;">loc</span><span style="color: #e06c75;">=</span><span style="color: #c678dd;">2</span><span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">fontsize</span><span style="color: #e06c75;">=</span><span style="color: #c678dd;">13</span>) <span style="color: #848d9b;"># 與 loc="upper left" 等價</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">plt<span style="color: #abb2bf;">.</span>show()</span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># --------------------------------------------------------------------</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># net 模型在神經網路訓練階段,也就是上述 [for i in range(numEpochs)...],其</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 相關參數尚在優化調整過程,屬未定態;也就是說,在此階段,net 模型的權重參數及偏權</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 值參數還在學習,還在不斷更新以朝向最優解。</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 至於最後的 predY = net(x),則是將訓練資料集的 x 代入「已訓練好的」net 模型並</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 輸出預測值。此時 net 模型中的相關參數已優化結束了。</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># --------------------------------------------------------------------</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># x, y, predY 原屬 torch.FloatTensor 型態的資料矩陣(15x1),為使 matplotlib</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 順利進行繪圖,故將 torch.FloatTensor 利用 .data.numpy() 轉型為 numpy 型別</span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># 為 float32 之資料矩陣(15x1)。 </span></span></div><div><span style="color: #848d9b;"><span style="font-family: Source Code Pro; font-size: x-small;"># --------------------------------------------------------------------</span></span></div><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span><div><span style="font-family: Source Code Pro; font-size: x-small;">輸出:</span></div><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span><div><span style="font-family: Source Code Pro; font-size: x-small;">神經網路模型訓練前參數值<span style="color: #56b6c2;">...</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">hidden<span style="color: #abb2bf;">.</span>weight : tensor([[<span style="color: #e06c75;">-</span><span style="color: #c678dd;">0.3983</span>]])</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">hidden<span style="color: #abb2bf;">.</span>bias : tensor([<span style="color: #c678dd;">0.2115</span>])</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">weight 權重之 shape: torch<span style="color: #abb2bf;">.</span>Size([<span style="color: #c678dd;">1</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">1</span>])</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">bias 偏權值之 shape: torch<span style="color: #abb2bf;">.</span>Size([<span style="color: #c678dd;">1</span>])</span></div><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span><div><span style="font-family: Source Code Pro; font-size: x-small;">神經網路模型訓練開始<span style="color: #56b6c2;">...</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">4</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">41.5495491027832</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">9</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">13.097318649291992</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">14</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">6.5602922439575195</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">19</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">5.057382583618164</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">24</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">4.710859775543213</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">29</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">4.629976749420166</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">34</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">4.610118389129639</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">39</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">4.6042866706848145</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">44</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">4.601683616638184</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #56b6c2;">.........</span>.<span style="color: #abb2bf;">.</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">略 <span style="color: #56b6c2;">......</span>.<span style="color: #abb2bf;">.</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #56b6c2;">.........</span>.<span style="color: #abb2bf;">.</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">1954</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">4.3385491371154785</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">1959</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">4.3383469581604</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">1964</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">4.338144779205322</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">1969</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">4.337944984436035</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">1974</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">4.337744235992432</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">1979</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">4.337545871734619</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">1984</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">4.337348461151123</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">1989</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">4.337152004241943</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">1994</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">4.33695650100708</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">1999</span><span style="color: #e06c75;">/</span><span style="color: #c678dd;">2000</span> <span style="color: #e06c75;">=></span> loss:<span style="color: #c678dd;">4.336761951446533</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">神經網路模型訓練結束<span style="color: #56b6c2;">...</span></span></div><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span><div><span style="font-family: Source Code Pro; font-size: x-small;">神經網路模型訓練後參數值<span style="color: #56b6c2;">...</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">hidden<span style="color: #abb2bf;">.</span>weight : tensor([[<span style="color: #c678dd;">0.8444</span>]])</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">hidden<span style="color: #abb2bf;">.</span>bias : tensor([<span style="color: #c678dd;">1.0582</span>])</span></div></div><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-vggVF87Wo1Q/X_1YCGDs25I/AAAAAAAAVCA/LnDoStCoD7svXAKHYtN-QoIMJwrmbmDrACLcBGAsYHQ/s481/Linear.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="364" data-original-width="481" src="https://1.bp.blogspot.com/-vggVF87Wo1Q/X_1YCGDs25I/AAAAAAAAVCA/LnDoStCoD7svXAKHYtN-QoIMJwrmbmDrACLcBGAsYHQ/s16000/Linear.png" /></a></div><br /><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span><p></p><p><span style="font-family: Source Code Pro; font-size: x-small;"> </span></p><p><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span></p><p><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span></p><p><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span></p><p><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span></p><p><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span></p><p><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span></p><p><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span></p><p><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span></p><p><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span></p><p><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span></p><p><span style="font-family: Source Code Pro;"><b>隨筆心得:</b></span></p><p><span style="font-family: Source Code Pro;"></span></p><div class="separator" style="clear: both; text-align: center;"><span style="font-family: Source Code Pro;"><a href="https://1.bp.blogspot.com/-uj8T6pGr1BY/X_57Ck630uI/AAAAAAAAVCU/fOyfkAvm9qYdcvyAYYqVjAVPYP2izpVuwCLcBGAsYHQ/s755/%25E7%25A5%259E%25E7%25B6%2593%25E5%2585%2583.jpg" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="755" data-original-width="649" src="https://1.bp.blogspot.com/-uj8T6pGr1BY/X_57Ck630uI/AAAAAAAAVCU/fOyfkAvm9qYdcvyAYYqVjAVPYP2izpVuwCLcBGAsYHQ/s16000/%25E7%25A5%259E%25E7%25B6%2593%25E5%2585%2583.jpg" /></a></span></div><span style="font-family: Source Code Pro;"><br /><b><br /></b></span><p></p><p></p><div class="separator" style="clear: both; text-align: center;"><br /></div><br /><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span><p></p><p><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span></p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-18826742774923020502020-12-21T16:58:00.016+08:002021-01-06T20:47:42.979+08:00揮灑Python(72):多變數二次函數之回歸分析 numpy 版本(損失函數、偏導數與梯度下降)<div><div style="background-color: #282c34; color: #bbbbbb; font-family: "Source Code Pro", Consolas, "Courier New", monospace; line-height: 20px; white-space: pre;"><div><span style="font-size: x-small;"><span style="color: #e06c75;">import</span> numpy <span style="color: #e06c75;">as</span> np </span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">import</span> matplotlib<span style="color: #abb2bf;">.</span>pyplot <span style="color: #e06c75;">as</span> plt</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># ---------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;">plt<span style="color: #abb2bf;">.</span>rcParams[<span style="color: #e5c07b;">"font.family"</span>] <span style="color: #e06c75;">=</span> <span style="color: #e5c07b;">"sans-serif"</span></span></div><div><span style="font-size: x-small;">plt<span style="color: #abb2bf;">.</span>rcParams[<span style="color: #e5c07b;">"font.sans-serif"</span>] <span style="color: #e06c75;">=</span> [<span style="color: #e5c07b;">"Microsoft JhengHei"</span>]</span></div><div><span style="font-size: x-small;">plt<span style="color: #abb2bf;">.</span>rcParams[<span style="color: #e5c07b;">'axes.unicode_minus'</span>] <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">False</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># ---------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># matplotlib 設定中文顯示字型及正常顯示座標軸之負號</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># --------------------------------------------------------------- </span></span></div><div><span style="font-size: x-small;">np<span style="color: #abb2bf;">.</span>random<span style="color: #abb2bf;">.</span>seed(<span style="color: #c678dd;">10</span>)</span></div><div><span style="font-size: x-small;">x <span style="color: #e06c75;">=</span> np<span style="color: #abb2bf;">.</span>linspace(<span style="color: #e06c75;">-</span><span style="color: #c678dd;">2</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">2</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">100</span>)</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># print(x)</span></span></div><div><span style="font-size: x-small;">y <span style="color: #e06c75;">=</span> np<span style="color: #abb2bf;">.</span>array([<span style="color: #c678dd;">3</span><span style="color: #e06c75;">*</span>np<span style="color: #abb2bf;">.</span>power(xi<span style="color: #abb2bf;">,</span><span style="color: #c678dd;">2</span>)<span style="color: #e06c75;">+</span><span style="color: #c678dd;">2</span><span style="color: #e06c75;">+</span>np<span style="color: #abb2bf;">.</span>random<span style="color: #abb2bf;">.</span>rand() <span style="color: #e06c75;">for</span> xi <span style="color: #e06c75;">in</span> x]<span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">dtype</span><span style="color: #e06c75;">=</span>np<span style="color: #abb2bf;">.</span>float32)</span></div><div><span style="font-size: x-small;">loss <span style="color: #e06c75;">=</span> np<span style="color: #abb2bf;">.</span>array([])</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># --------------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># np.random.seed(n):當設定 seed(n) ,假若 n 值不變,則每次產生的隨機亂數</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 也會相同;反之,每次的 n 值不同,=> 產生的隨機亂數值也會不同。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 但若不設定 np.random.seed(n) => 由系統根據時間決定亂數種子值,故每次生成</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 的隨機亂數也就跟著不同。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># --------------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># linspace(start, stop, num):從 start~end 佈點且平均間隔切成(steps-1)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 等分,上例而言:-2~2 佈設 100 點(包含起點與終點),併切割 (100-1) 等分,故</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 每一等份間隔距離 = (終點-起點)/(steps-1) = (2-(-2))/(100-1)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># = 0.04040404</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 第 1 點:-2</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 第 2 點:-2+0.04040404=-1.95959596</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 第 3 點:-1.95959596+0.04040404=-1.91919192</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># .....</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 第 100 點:2</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># --------------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;">w <span style="color: #e06c75;">=</span> np<span style="color: #abb2bf;">.</span>random<span style="color: #abb2bf;">.</span>rand() <span style="color: #676f7d;"># [0,1) 之間隨機值</span></span></div><div><span style="font-size: x-small;">b <span style="color: #e06c75;">=</span> np<span style="color: #abb2bf;">.</span>random<span style="color: #abb2bf;">.</span>rand() <span style="color: #676f7d;"># [0,1) 之間隨機值 </span></span></div><div><span style="font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #56b6c2;">f</span><span style="color: #e5c07b;">"初始化,w:</span><span style="color: #56b6c2;">{</span>w<span style="color: #56b6c2;">}</span><span style="color: #e5c07b;">, b:</span><span style="color: #56b6c2;">{</span>b<span style="color: #56b6c2;">}</span><span style="color: #e5c07b;">"</span>) <span style="color: #676f7d;"># 0 <= w < 1 , 0 <= b < 1 </span></span></div><div><span style="font-size: x-small;">lr <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">0.001</span> <span style="color: #676f7d;"># learning rate 學習率</span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">for</span> i <span style="color: #e06c75;">in</span> <span style="color: #98c379;">range</span>(<span style="color: #c678dd;">1</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">501</span>)<span style="color: #abb2bf;">:</span></span></div><div><span style="font-size: x-small;"> predY <span style="color: #e06c75;">=</span> w <span style="color: #e06c75;">*</span> np<span style="color: #abb2bf;">.</span>power(x<span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">2</span>) <span style="color: #e06c75;">+</span> b <span style="color: #676f7d;"># 回歸方程式:y=w*x^2+b</span></span></div><div><span style="font-size: x-small;"> loss <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">0.5</span> <span style="color: #e06c75;">*</span> np<span style="color: #abb2bf;">.</span>sum(np<span style="color: #abb2bf;">.</span>power(predY<span style="color: #e06c75;">-</span>y<span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">2</span>)) <span style="color: #676f7d;"># 計算損失函數(誤差值)</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># -----------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># 本例為手動演算後直接代入式子計算 w、b 的梯度 => 求偏導數</span></span></div><div><span style="font-size: x-small;"><span style="color: #676f7d;"><span> </span># 若使用 pytorch 深度學習框架,則可透過 loss.backward() 對損失函數進行梯度</span></span></div><div><span style="font-size: x-small;"><span style="color: #676f7d;"><span> # 反傳,也就是說,利用 backward() 將損失函數反向傳播以計算網路中 w, b 的梯度</span><br /></span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># 深度學習編程常用 w 表示 weight 權重值;b 表示 bias 偏權值、偏置值</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># -----------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> gredW <span style="color: #e06c75;">=</span> np<span style="color: #abb2bf;">.</span>sum((predY<span style="color: #e06c75;">-</span>y)<span style="color: #e06c75;">*</span>np<span style="color: #abb2bf;">.</span>power(x<span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">2</span>)) <span style="color: #676f7d;"># 代入式子直接求 w 的梯度</span></span></div><div><span style="font-size: x-small;"> gredB <span style="color: #e06c75;">=</span> np<span style="color: #abb2bf;">.</span>sum(predY<span style="color: #e06c75;">-</span>y) <span style="color: #676f7d;"># </span></span><span style="color: #676f7d; font-size: small;">代入式子直接求 b 的梯度</span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># -----------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> w <span style="color: #e06c75;">=</span> w <span style="color: #e06c75;">-</span> lr <span style="color: #e06c75;">*</span> gredW <span style="color: #676f7d;"># 梯度下降法更新 w 參數值</span></span></div><div><span style="font-size: x-small;"> b <span style="color: #e06c75;">=</span> b <span style="color: #e06c75;">-</span> lr <span style="color: #e06c75;">*</span> gredB <span style="color: #676f7d;"># 梯度下降法更新 b 參數值</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># -----------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># 回歸方程式: y = w * x^2 + b</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># predY:為訓練集資料樣本點餵給回歸方程式後輸出所得資料集合.</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># loss:損失函數,predY 與訓練集資料中的 y 進行誤差計算,本例採用均方誤差</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># (Mean Squared Error)。根據推導,loss 最終可以表成以 w, b 變數</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># 為主的多變數二次函數(三維空間的曲面),當 loss 趨近最小值,則所預測</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># 的回歸曲線越趨近訓練資料樣本點,故問題要旨即在求解 loss 函數的最小</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># 值,關於函數最小值求解,可透過微積分.</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># lr:learning rate 學習率,用來控制梯度下降的速率快慢,以下山為喻,下山</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># 過程是沿著梯度反方向而行,至於每次該行走多少距離,則由學習率來決定</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># gredW:loss 函數對變數 w 求偏導數。</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># gredB:loss 函數對變數 b 求偏導數。</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># gredW 及 gredB 構成曲面上某點的梯度,藉由梯度下降法便可更新 w,b 變數。</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># -----------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># 梯度下降法更新 w, b 參數,具體方式:</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># w = w - lr * gredW</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># b = b - lr * gredB</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># 深度學習中的「反向傳播法」是非常重要的演算法,此法核心概念就是將誤差值往</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># 回傳遞,並藉以計算誤差值(損失函數)相對於各權重參數 w 及偏權參數 b 的梯度,</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># 後續再利用梯度下降法來更新參數 w,b 值,最終目標在於降低損失函數至最小值。</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># -----------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #56b6c2;">f</span><span style="color: #e5c07b;">"</span><span style="color: #56b6c2;">{</span>i<span style="color: #56b6c2;">}</span><span style="color: #e5c07b;">'s loss:</span><span style="color: #56b6c2;">{</span>loss<span style="color: #56b6c2;">}</span><span style="color: #e5c07b;">,w:</span><span style="color: #56b6c2;">{</span>w<span style="color: #56b6c2;">}</span><span style="color: #e5c07b;">,gredW:</span><span style="color: #56b6c2;">{</span>gredW<span style="color: #56b6c2;">}</span><span style="color: #e5c07b;">;b:</span><span style="color: #56b6c2;">{</span>b<span style="color: #56b6c2;">}</span><span style="color: #e5c07b;">,gredB:</span><span style="color: #56b6c2;">{</span>gredB<span style="color: #56b6c2;">}</span><span style="color: #e5c07b;">"</span>)</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># ---------------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 根據梯度下降法進行 500 次迭代運算,梯度為函數變化率最大的方向,也就是說梯度方</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 向為函數上升最快的方向,反之,梯度逆(反)方向則為函數下降最快的方向,本例在求多</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 變數二次函數的最小值,因此更新 w,b 參數值的方式,卻要以梯度的逆方向而行,這就</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 是梯度下降法的原理。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># ---------------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;">plt<span style="color: #abb2bf;">.</span>figure(<span style="color: #d19a66; font-style: italic;">figsize</span><span style="color: #e06c75;">=</span>(<span style="color: #c678dd;">8</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">6</span>)) </span></div><div><span style="font-size: x-small;">plt<span style="color: #abb2bf;">.</span>plot(x<span style="color: #abb2bf;">,</span> y<span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">"."</span><span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">color</span><span style="color: #e06c75;">=</span><span style="color: #e5c07b;">"#006AFF"</span><span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">label</span><span style="color: #e06c75;">=</span><span style="color: #e5c07b;">"訓練集樣本點"</span>)</span></div><div><span style="font-size: x-small;">plt<span style="color: #abb2bf;">.</span>plot(x<span style="color: #abb2bf;">,</span> predY<span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">""</span><span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">color</span><span style="color: #e06c75;">=</span><span style="color: #e5c07b;">"#FF0077"</span><span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">label</span><span style="color: #e06c75;">=</span><span style="color: #e5c07b;">"回歸預測曲線"</span>)</span></div><div><span style="font-size: x-small;">plt<span style="color: #abb2bf;">.</span>legend(<span style="color: #d19a66; font-style: italic;">loc</span><span style="color: #e06c75;">=</span><span style="color: #c678dd;">3</span><span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">fontsize</span><span style="color: #e06c75;">=</span><span style="color: #c678dd;">13</span>) <span style="color: #676f7d;"># 與 loc="lower left" 等價</span></span></div><div><span style="font-size: x-small;">plt<span style="color: #abb2bf;">.</span>show() </span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># ---------------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># plt.figure(figsize=(8, 6)) 之 figsize 以英寸為單位,分別設定寬度和高度</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># plt.legend 之 loc 參數用來設定圖例位置,參數值如下:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 0: 'best'</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 1: 'upper right'</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 2: 'upper left'</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 3: 'lower left'</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 4: 'lower right'</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 5: 'right'</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 6: 'center left'</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 7: 'center right'</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 8: 'lower center'</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 9: 'upper center'</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;">#10: 'center'</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># ---------------------------------------------------------------------</span></span></div><span style="font-size: x-small;"><br /></span></div></div><div><span style="font-size: x-small;"><br /></span></div><div><div><span style="font-family: arial; font-size: medium;">執行結果:</span></div><div><span style="font-family: arial; font-size: medium;">先把統計圖及相關原理說明放上來,最後接著數據輸出。</span></div><div><span style="font-family: arial; font-size: xx-small;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-WB0yIRAEApk/X-BRgxgqzVI/AAAAAAAAU3s/AqnAnP2OGNIT8pdxH-Py_QT19Uc2QldDQCLcBGAsYHQ/s483/%25E4%25BA%258C%25E6%25AC%25A1.jpg" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="367" data-original-width="483" src="https://1.bp.blogspot.com/-WB0yIRAEApk/X-BRgxgqzVI/AAAAAAAAU3s/AqnAnP2OGNIT8pdxH-Py_QT19Uc2QldDQCLcBGAsYHQ/s16000/%25E4%25BA%258C%25E6%25AC%25A1.jpg" /></a></div><br /><span style="font-family: arial; font-size: xx-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><span style="font-family: inherit; font-size: x-small;"><br /></span></div><div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-1UfOmLLzF8s/X-B71LkP3PI/AAAAAAAAU5s/yzJ2g6Val8YB45qKmU9SRSqZq0NePETkACLcBGAsYHQ/s1037/%25E5%259B%259E%25E6%25AD%25B8%25E5%2588%2586%25E6%259E%2590_0.jpg" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1037" data-original-width="707" src="https://1.bp.blogspot.com/-1UfOmLLzF8s/X-B71LkP3PI/AAAAAAAAU5s/yzJ2g6Val8YB45qKmU9SRSqZq0NePETkACLcBGAsYHQ/s16000/%25E5%259B%259E%25E6%25AD%25B8%25E5%2588%2586%25E6%259E%2590_0.jpg" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-uBjUyAZpdh4/X-B75h5kE2I/AAAAAAAAU5w/owWjjBiyVjkkLc51lYuconYFACVqNu24QCLcBGAsYHQ/s1035/%25E5%259B%259E%25E6%25AD%25B8%25E5%2588%2586%25E6%259E%2590_1.jpg" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1035" data-original-width="709" src="https://1.bp.blogspot.com/-uBjUyAZpdh4/X-B75h5kE2I/AAAAAAAAU5w/owWjjBiyVjkkLc51lYuconYFACVqNu24QCLcBGAsYHQ/s16000/%25E5%259B%259E%25E6%25AD%25B8%25E5%2588%2586%25E6%259E%2590_1.jpg" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-x3R7GIR7u68/X-B79m2fttI/AAAAAAAAU50/DqJhU-HVe8c_KWSlTvVNNcMzvE9fH8NXwCLcBGAsYHQ/s1013/%25E5%259B%259E%25E6%25AD%25B8%25E5%2588%2586%25E6%259E%2590_2.jpg" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="1013" data-original-width="709" src="https://1.bp.blogspot.com/-x3R7GIR7u68/X-B79m2fttI/AAAAAAAAU50/DqJhU-HVe8c_KWSlTvVNNcMzvE9fH8NXwCLcBGAsYHQ/s16000/%25E5%259B%259E%25E6%25AD%25B8%25E5%2588%2586%25E6%259E%2590_2.jpg" /></a></div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-QyUCgn38e6k/X-B-OvGCZAI/AAAAAAAAU6Q/aFNma3HMzDo16L5UDJPMvHIUHBbxTsTXQCLcBGAsYHQ/s708/%25E5%259B%259E%25E6%25AD%25B8%25E5%2588%2586%25E6%259E%2590.jpg" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="665" data-original-width="708" src="https://1.bp.blogspot.com/-QyUCgn38e6k/X-B-OvGCZAI/AAAAAAAAU6Q/aFNma3HMzDo16L5UDJPMvHIUHBbxTsTXQCLcBGAsYHQ/s16000/%25E5%259B%259E%25E6%25AD%25B8%25E5%2588%2586%25E6%259E%2590.jpg" /></a></div><br /></div></div><div><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;"><span><br /></span></span></span></p><p class="MsoNormal"><span style="font-family: times; font-size: x-small;"><br /></span></p><p class="MsoNormal"><span style="font-family: times; font-size: x-small;"><br /></span></p><p class="MsoNormal"><span style="font-family: times; font-size: x-small;">初始化,</span><span lang="EN-US" style="color: #cc0000; font-family: times; font-size: x-small;">w</span><span style="font-family: times; font-size: x-small;">:</span><span lang="EN-US" style="font-family: times; font-size: x-small;">0.5781364298824675, <span style="color: #5d2884;">b</span></span><span style="font-family: times; font-size: x-small;">:</span><span lang="EN-US" style="font-family: times; font-size: x-small;">0.8539337505004864</span></p><p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">1's <span style="color: #cc0000;">loss</span>:1649.2197770425537,<span style="color: #009900;">w</span>:1.605858141031899,<span style="color: #0033cc;">gredW</span>:-1027.7217111494317;<span style="color: #5d2884;">b</span>:1.3465139344661816,<span style="color: #ff6600;">gredB</span>:-492.58018396569514<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">2's <span style="color: #cc0000;">loss</span>:607.2334879441582,<span style="color: #009900;">w</span>:2.2243284406591473,<span style="color: #0033cc;">gredW</span>:-618.4702996272484;<span style="color: #5d2884;">b</span>:1.6500382645792904,<span style="color: #ff6600;">gredB</span>:-303.5243301131087<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">3's <span style="color: #cc0000;">loss</span>:226.43251954423357,<span style="color: #009900;">w</span>:2.5955510723134956,<span style="color: #0033cc;">gredW</span>:-371.2226316543483;<span style="color: #5d2884;">b</span>:1.8390815417991324,<span style="color: #ff6600;">gredB</span>:-189.0432772198421<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">4's <span style="color: #cc0000;">loss</span>:87.16757230157612,<span style="color: #009900;">w</span>:2.8174358435388593,<span style="color: #0033cc;">gredW</span>:-221.88477122536364;<span style="color: #5d2884;">b</span>:1.9587242141291934,<span style="color: #ff6600;">gredB</span>:-119.64267233006105<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">5's <span style="color: #cc0000;">loss</span>:36.14481256280837,<span style="color: #009900;">w</span>:2.9491549251632683,<span style="color: #0033cc;">gredW</span>:-131.71908162440883;<span style="color: #5d2884;">b</span>:2.0362203136454244,<span style="color: #ff6600;">gredB</span>:-77.49609951623104<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">6's <span style="color: #cc0000;">loss</span>:17.36695250833702,<span style="color: #009900;">w</span>:3.0264679567004062,<span style="color: #0033cc;">gredW</span>:-77.3130315371378;<span style="color: #5d2884;">b</span>:2.088049460120382,<span style="color: #ff6600;">gredB</span>:-51.829146474957696<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">7's <span style="color: #cc0000;">loss</span>:10.378037020940546,<span style="color: #009900;">w</span>:3.0709843919828375,<span style="color: #0033cc;">gredW</span>:-44.51643528243109;<span style="color: #5d2884;">b</span>:2.124179037152893,<span style="color: #ff6600;">gredB</span>:-36.129577032511165<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">8's <span style="color: #cc0000;">loss</span>:7.704995824858906,<span style="color: #009900;">w</span>:3.0957615695638965,<span style="color: #0033cc;">gredW</span>:-24.777177581059064;<span style="color: #5d2884;">b</span>:2.1506402221878425,<span style="color: #ff6600;">gredB</span>:-26.46118503494957<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">9's <span style="color: #cc0000;">loss</span>:6.617307033252673,<span style="color: #009900;">w</span>:3.1086881295501554,<span style="color: #0033cc;">gredW</span>:-12.926559986258729;<span style="color: #5d2884;">b</span>:2.1710849251695503,<span style="color: #ff6600;">gredB</span>:-20.444702981707877<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">10's <span style="color: #cc0000;">loss</span>:6.116896418682215,<span style="color: #009900;">w</span>:3.114528914660744,<span style="color: #0033cc;">gredW</span>:-5.840785110588566;<span style="color: #5d2884;">b</span>:2.187726797504788,<span style="color: #ff6600;">gredB</span>:-16.641872335237892<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">11's <span style="color: #cc0000;">loss</span>:5.838579738099289,<span style="color: #009900;">w</span>:3.1161608850140214,<span style="color: #0033cc;">gredW</span>:-1.6319703532773455;<span style="color: #5d2884;">b</span>:2.201909978503917,<span style="color: #ff6600;">gredB</span>:-14.183180999129002<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">12's <span style="color: #cc0000;">loss</span>:5.6484039350505615,<span style="color: #009900;">w</span>:3.115320089323274,<span style="color: #0033cc;">gredW</span>:0.8407956907470542;<span style="color: #5d2884;">b</span>:2.2144528494762903,<span style="color: #ff6600;">gredB</span>:-12.542870972372983<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">13's <span style="color: #cc0000;">loss</span>:5.496922737625874,<span style="color: #009900;">w</span>:3.113053123305223,<span style="color: #0033cc;">gredW</span>:2.266966018050913;<span style="color: #5d2884;">b</span>:2.225855804213063,<span style="color: #ff6600;">gredB</span>:-11.402954736772662<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">14's <span style="color: #cc0000;">loss</span>:5.365596989166379,<span style="color: #009900;">w</span>:3.1099899830680076,<span style="color: #0033cc;">gredW</span>:3.0631402372157597;<span style="color: #5d2884;">b</span>:2.236426831917671,<span style="color: #ff6600;">gredB</span>:-10.571027704608033<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">15's <span style="color: #cc0000;">loss</span>:5.247212553474315,<span style="color: #009900;">w</span>:3.1065089714361083,<span style="color: #0033cc;">gredW</span>:3.4810116318994173;<span style="color: #5d2884;">b</span>:2.2463574264329074,<span style="color: #ff6600;">gredB</span>:-9.930594515236514<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">16's <span style="color: #cc0000;">loss</span>:5.138724638132493,<span style="color: #009900;">w</span>:3.1028363622168422,<span style="color: #0033cc;">gredW</span>:3.6726092192661097;<span style="color: #5d2884;">b</span>:2.2557684728431817,<span style="color: #ff6600;">gredB</span>:-9.411046410274256<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">17's <span style="color: #cc0000;">loss</span>:5.038641528953146,<span style="color: #009900;">w</span>:3.099106632909459,<span style="color: #0033cc;">gredW</span>:3.7297293073833195;<span style="color: #5d2884;">b</span>:2.2647379883917496,<span style="color: #ff6600;">gredB</span>:-8.969515548567864<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">18's <span style="color: #cc0000;">loss</span>:4.946066692077205,<span style="color: #009900;">w</span>:3.0953988654777667,<span style="color: #0033cc;">gredW</span>:3.707767431692357;<span style="color: #5d2884;">b</span>:2.273317896035354,<span style="color: #ff6600;">gredB</span>:-8.579907643604296<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">19's <span style="color: #cc0000;">loss</span>:4.860346820049133,<span style="color: #009900;">w</span>:3.0917587434467673,<span style="color: #0033cc;">gredW</span>:3.6401220309996005;<span style="color: #5d2884;">b</span>:2.2815441691578315,<span style="color: #ff6600;">gredB</span>:-8.22627312247741<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">20's <span style="color: #cc0000;">loss</span>:4.780941372149754,<span style="color: #009900;">w</span>:3.0882118436713,<span style="color: #0033cc;">gredW</span>:3.546899775466902;<span style="color: #5d2884;">b</span>:2.289442969614702,<span style="color: #ff6600;">gredB</span>:-7.89880045687066<o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-family: times; font-size: xx-small;">......... 略 ....................</span></p>
<p class="MsoNormal"><span style="font-family: times; font-size: xx-small;">480's <span style="color: #cc0000;">loss</span>:3.7788896453772947,<span style="color: #009900;">w</span>:2.9951836479947374,<span style="color: #0033cc;">gredW</span>:8.758909347816868e-08;<span style="color: #5d2884;">b</span>:2.4919003152027677,<span style="color: #ff6600;">gredB</span>:-1.9034563125686077e-07</span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">481's <span style="color: #cc0000;">loss</span>:3.7788896453772938,<span style="color: #009900;">w</span>:2.995183647910425,<span style="color: #0033cc;">gredW</span>:8.431270692721426e-08;<span style="color: #5d2884;">b</span>:2.491900315385993,<span style="color: #ff6600;">gredB</span>:-1.8322554584671025e-07<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">482's <span style="color: #cc0000;">loss</span>:3.7788896453772933,<span style="color: #009900;">w</span>:2.9951836478292657,<span style="color: #0033cc;">gredW</span>:8.115890931525982e-08;<span style="color: #5d2884;">b</span>:2.491900315562365,<span style="color: #ff6600;">gredB</span>:-1.763717851765989e-07<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">483's <span style="color: #cc0000;">loss</span>:3.778889645377293,<span style="color: #009900;">w</span>:2.995183647751143,<span style="color: #0033cc;">gredW</span>:7.812296448639344e-08;<span style="color: #5d2884;">b</span>:2.4919003157321393,<span style="color: #ff6600;">gredB</span>:-1.6977443539900605e-07<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">484's <span style="color: #cc0000;">loss</span>:3.7788896453772955,<span style="color: #009900;">w</span>:2.995183647675942,<span style="color: #0033cc;">gredW</span>:7.520074629674411e-08;<span style="color: #5d2884;">b</span>:2.4919003158955633,<span style="color: #ff6600;">gredB</span>:-1.6342380204648066e-07<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">485's <span style="color: #cc0000;">loss</span>:3.7788896453772938,<span style="color: #009900;">w</span>:2.9951836476035543,<span style="color: #0033cc;">gredW</span>:7.238780658225252e-08;<span style="color: #5d2884;">b</span>:2.491900316052874,<span style="color: #ff6600;">gredB</span>:-1.5731073244040772e-07<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">486's <span style="color: #cc0000;">loss</span>:3.778889645377294,<span style="color: #009900;">w</span>:2.9951836475338744,<span style="color: #0033cc;">gredW</span>:6.968001292628756e-08;<span style="color: #5d2884;">b</span>:2.4919003162043003,<span style="color: #ff6600;">gredB</span>:-1.5142636788922914e-07<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">487's <span style="color: #cc0000;">loss</span>:3.778889645377296,<span style="color: #009900;">w</span>:2.995183647466801,<span style="color: #0033cc;">gredW</span>:6.707364202940269e-08;<span style="color: #5d2884;">b</span>:2.4919003163500624,<span style="color: #ff6600;">gredB</span>:-1.457620513178881e-07<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">488's <span style="color: #cc0000;">loss</span>:3.778889645377296,<span style="color: #009900;">w</span>:2.995183647402236,<span style="color: #0033cc;">gredW</span>:6.456466544735306e-08;<span style="color: #5d2884;">b</span>:2.491900316490372,<span style="color: #ff6600;">gredB</span>:-1.4030965633793357e-07<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">489's <span style="color: #cc0000;">loss</span>:3.7788896453772933,<span style="color: #009900;">w</span>:2.995183647340087,<span style="color: #0033cc;">gredW</span>:6.214951520089329e-08;<span style="color: #5d2884;">b</span>:2.491900316625433,<span style="color: #ff6600;">gredB</span>:-1.350612373052229e-07<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">490's <span style="color: #cc0000;">loss</span>:3.778889645377295,<span style="color: #009900;">w</span>:2.995183647280262,<span style="color: #0033cc;">gredW</span>:5.982471290577607e-08;<span style="color: #5d2884;">b</span>:2.4919003167554425,<span style="color: #ff6600;">gredB</span>:-1.300091208022991e-07<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">491's <span style="color: #cc0000;">loss</span>:3.778889645377294,<span style="color: #009900;">w</span>:2.9951836472226754,<span style="color: #0033cc;">gredW</span>:5.7587019708371656e-08;<span style="color: #5d2884;">b</span>:2.4919003168805887,<span style="color: #ff6600;">gredB</span>:-1.251459242901376e-07<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">492's <span style="color: #cc0000;">loss</span>:3.7788896453772924,<span style="color: #009900;">w</span>:2.9951836471672424,<span style="color: #0033cc;">gredW</span>:5.543295078513921e-08;<span style="color: #5d2884;">b</span>:2.491900317001053,<span style="color: #ff6600;">gredB</span>:-1.2046467778858982e-07<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">493's <span style="color: #cc0000;">loss</span>:3.778889645377297,<span style="color: #009900;">w</span>:2.995183647113883,<span style="color: #0033cc;">gredW</span>:5.335932823369305e-08;<span style="color: #5d2884;">b</span>:2.491900317117012,<span style="color: #ff6600;">gredB</span>:-1.1595860760493792e-07<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">494's <span style="color: #cc0000;">loss</span>:3.778889645377292,<span style="color: #009900;">w</span>:2.9951836470625195,<span style="color: #0033cc;">gredW</span>:5.1363281461380694e-08;<span style="color: #5d2884;">b</span>:2.491900317228633,<span style="color: #ff6600;">gredB</span>:-1.1162106439144281e-07<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">495's <span style="color: #cc0000;">loss</span>:3.778889645377293,<span style="color: #009900;">w</span>:2.9951836470130777,<span style="color: #0033cc;">gredW</span>:4.944195314271482e-08;<span style="color: #5d2884;">b</span>:2.4919003173360785,<span style="color: #ff6600;">gredB</span>:-1.0744576517396354e-07<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">496's <span style="color: #cc0000;">loss</span>:3.778889645377295,<span style="color: #009900;">w</span>:2.995183646965485,<span style="color: #0033cc;">gredW</span>:4.7592574159427414e-08;<span style="color: #5d2884;">b</span>:2.491900317439505,<span style="color: #ff6600;">gredB</span>:-1.0342661882489779e-07<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">497's <span style="color: #cc0000;">loss</span>:3.7788896453772933,<span style="color: #009900;">w</span>:2.995183646919673,<span style="color: #0033cc;">gredW</span>:4.5812288740343377e-08;<span style="color: #5d2884;">b</span>:2.491900317539063,<span style="color: #ff6600;">gredB</span>:-9.95578379736628e-08<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">498's <span style="color: #cc0000;">loss</span>:3.778889645377295,<span style="color: #009900;">w</span>:2.9951836468755744,<span style="color: #0033cc;">gredW</span>:4.4098640961109936e-08;<span style="color: #5d2884;">b</span>:2.4919003176348964,<span style="color: #ff6600;">gredB</span>:-9.583376625599271e-08<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">499's <span style="color: #cc0000;">loss</span>:3.778889645377296,<span style="color: #009900;">w</span>:2.995183646833125,<span style="color: #0033cc;">gredW</span>:4.2449118276000064e-08;<span style="color: #5d2884;">b</span>:2.4919003177271453,<span style="color: #ff6600;">gredB</span>:-9.224898978033025e-08<o:p></o:p></span></span></p>
<p class="MsoNormal"><span lang="EN-US"><span style="font-family: times; font-size: xx-small;">500's <span style="color: #cc0000;">loss</span>:3.778889645377294,<span style="color: #009900;">w</span>:2.995183646792264,<span style="color: #0033cc;">gredW</span>:4.0861225958366276e-08;<span style="color: #5d2884;">b</span>:2.4919003178159436,<span style="color: #ff6600;">gredB</span>:-8.879833179875618e-08</span><span style="font-size: 8pt;"><o:p></o:p></span></span></p><br />文獻參考:</div><div><span style="font-family: Source Sans Pro;"><span lang="EN-US">1.<a href="https://www.brilliantcode.net/1326/backpropagation-1-gradient-descent-chain-rule/" target="_blank">Backpropagation(BP) </a></span><a href="https://www.brilliantcode.net/1326/backpropagation-1-gradient-descent-chain-rule/" target="_blank">倒傳遞法<span lang="EN-US"> #1 </span>工作原理與說明</a></span></div><div><span style="font-family: Source Sans Pro;"><span lang="EN-US">2.<a href="https://blog.csdn.net/walilk/article/details/50978864?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-6.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-6.control" target="_blank">[</a></span><a href="https://blog.csdn.net/walilk/article/details/50978864?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-6.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-6.control" target="_blank">机器学习<span lang="EN-US">] ML</span>重要概念:梯度(<span lang="EN-US">Gradient</span>)与梯度下降法(<span lang="EN-US">Gradient Descent</span>)</a></span></div><div><span style="font-family: Source Sans Pro;"><span lang="EN-US">3.</span><a href="https://blog.csdn.net/weixin_42398658/article/details/83017995?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-4.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-4.control" target="_blank"><span lang="ZH-CN">机器学习</span><span lang="EN-US">--</span><span lang="ZH-CN">什么是梯度?为什么梯度方向就是函数上升最快的方向?</span></a></span></div><div><span style="font-family: Source Sans Pro;">4.<a href="https://allen108108.github.io/blog/2020/06/01/%E7%82%BA%E4%BB%80%E9%BA%BC%E9%9C%80%E8%A6%81%E5%8F%8D%E5%90%91%E5%82%B3%E6%92%AD%20_%20Why%20Backpropagation%20_/" target="_blank">為什麼需要反向傳播 ? Why Backpropagation ?</a></span></div><div><span style="font-family: Source Sans Pro;">5.<a href="https://www.cnblogs.com/bigmonkey/p/8400658.html" target="_blank">多变量微积分笔记5——梯度与方向导数</a></span></div><div><span style="font-family: Source Sans Pro;">6.<a href="https://blog.csdn.net/qq_41800366/article/details/86583789" target="_blank">梯度下降算法原理讲解——机器学习</a></span></div><div><span style="font-family: Source Sans Pro;">7.<a href="https://www.youtube.com/watch?v=Dhou27Ergkk" target="_blank">5 分钟理解偏导数和梯度 - 数学知识的动画解析</a></span></div><div><br /></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-36916746693442764752020-11-27T16:25:00.004+08:002020-11-27T16:25:35.631+08:00揮灑Python(71):__call__() 函數 - 物件實例作為一般函數調用的實現<div style="background-color: #282c34; color: #bbbbbb; font-family: "Source Code Pro", Consolas, "Courier New", monospace; line-height: 20px; white-space: pre;"><div><span style="font-size: x-small;"><span style="color: #56b6c2;">class</span> <span style="color: #61afef;">Add</span>():</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">def</span> <span style="color: #98c379;">__init__</span>(<span style="color: #d19a66; font-style: italic;">self</span>):</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"物件實例被初始化..."</span>)</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">def</span> <span style="color: #98c379;">__call__</span>(<span style="color: #d19a66; font-style: italic;">self</span><span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">a</span><span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">b</span><span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">c</span>):</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"__call__() 函數被調用.."</span>)</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"a + b + c ="</span><span style="color: #abb2bf;">,</span> a<span style="color: #e06c75;">+</span>b<span style="color: #e06c75;">+</span>c) </span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>toDo()</span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># -----------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># python 中,類別衍生的物件實例可以被視為一般函數來使用,</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># 當然,這樣的函數也可接收參數傳遞。為達這樣的目的,可以透</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># 過 __call__ 方法實作來實現物件實例像函數般被調用。</span></span></div><div><span style="font-size: x-small;"> <span style="color: #676f7d;"># -----------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">def</span> <span style="color: #98c379;">toDo</span>(<span style="color: #d19a66; font-style: italic;">self</span>):</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"toDo() 函數被調用.."</span>)</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">adder <span style="color: #e06c75;">=</span> Add() </span></div><div><span style="font-size: x-small;">adder(<span style="color: #c678dd;">1</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">2</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">3</span>) </span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># ----------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># adder 是一個 Add 類的物件實例(instance),adder(1, 2, 3)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 就是把 adder 物件當作一般函數來調用,且帶參數傳遞。那麼究竟為</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># 何可如此施為呢?原因是:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># adder(1, 2, 3) => 相當於 adder.__call__(1, 2, 3)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># ----------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># adder.__call__(1, 2, 3) 可將本行 mark 取消實驗一下.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"># ----------------------------------------------------</span></span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">執行結果:</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">物件實例被初始化<span style="color: #56b6c2;">...</span></span></div><div><span style="font-size: x-small;"><span style="color: #98c379;">__call__</span>() 函數被調用.<span style="color: #abb2bf;">.</span></span></div><div><span style="font-size: x-small;">a <span style="color: #e06c75;">+</span> b <span style="color: #e06c75;">+</span> c <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">6</span></span></div><div><span style="font-size: x-small;">toDo() 函數被調用.<span style="color: #abb2bf;">.</span></span></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-52530916309554245692020-11-21T17:22:00.002+08:002020-11-21T17:22:14.630+08:00閒談C++(26):C++ 之 lambda expression<div style="background-color: #282c34; color: #bbbbbb; font-family: "Source Code Pro", Consolas, "Courier New", monospace; line-height: 20px; white-space: pre;"><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><iostream></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><vector></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><algorithm></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">using</span> <span style="color: #56b6c2;">namespace</span> std;</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> <span style="color: #98c379;">main</span>() {</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // lambda 運算式: [capture clause] (parameters) -> return-type { body };</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ~~~~~~~~~~~~~</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // [capture clause]:「捕捉子句」,一定要有。所有 lambda 運算式都要以此開頭,不可省略。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 就算沒有需要捕捉的外部變數,也要保留 [] 樣式,其功用在設定如何捕捉外部作用域的變數進行運</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 算。捕捉方式可分為傳址及傳值。含有「&」前置詞 => 捕捉來的變數以傳址方式進行存取;若不含</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> //「&」前置詞 => 捕捉來的變數以傳值方式進行存取。這裡所謂捕捉來的「變數」,係指原外部作用域</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 之變數,非指透過 (parameters) 傳進來的參數之謂。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // [capture clause] 簡述:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // []:不捕捉外部作用域的變數,即使不捕捉,也要保留空的 [] 樣式。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // [=]:所有外部作用域的變數均以傳值的方式捕捉(Capture by Value)。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // [&]:所有外部作用域的變數均以傳參考的方式捕捉(Capture by Reference)。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 更多 capture clause 可參考:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://openhome.cc/Gossip/CppGossip/Lambda.html</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // (parameters):選項,不一定要有。若把 lambda 運算式當作一種匿名函數,則 parameters</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 代表函數中的參數,若無需參數傳遞 => 可直接省略、或表示為「()」、或為「(void)」。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // return-type:lambda 運算式的回傳型別,可有可無,因為 compiler 可自動推斷回傳型別。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // body:lambda 運算式的主體,一定要有。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">auto</span> <span style="color: #abb2bf;">lambdaHello</span> <span style="color: #e06c75;">=</span> []() { <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"Hello Lambda"</span>; };</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">lambdaHello</span>();</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 這 lambdaHello() 的 lambda 運算式,沒有捕捉任何外部作用域變數,也沒有任何參數傳遞,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 也沒有指定回傳值,而函數主體為「{ cout << "Hello Lambda"; }」,以下敘述為等價:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // auto lambdaHello = [] { cout << "Hello Lambda"; }; // 省略()</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // auto lambdaHello = [](void) { cout << "Hello Lambda"; }; // void 無參數傳遞</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // auto lambdaHello = []() -> void { cout << "Hello Lambda"; }; // 無回傳值</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">auto</span> <span style="color: #abb2bf;">ldaSum</span> <span style="color: #e06c75;">=</span> [](<span style="color: #56b6c2;">int</span> <span style="color: #d19a66; font-style: italic;">x</span><span style="color: #abb2bf;">,</span> <span style="color: #56b6c2;">int</span> <span style="color: #d19a66; font-style: italic;">y</span><span style="color: #abb2bf;">,</span> <span style="color: #56b6c2;">int</span> <span style="color: #d19a66; font-style: italic;">z</span>) { <span style="color: #e06c75;">return</span> <span style="color: #d19a66; font-style: italic;">x</span><span style="color: #e06c75;">+</span><span style="color: #d19a66; font-style: italic;">y</span><span style="color: #e06c75;">+</span><span style="color: #d19a66; font-style: italic;">z</span>; };<span style="color: #676f7d;"> // 自動推斷回傳型別</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"ldaSum(1, 2, 3) = "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">ldaSum</span>(<span style="color: #c678dd;">1</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">2</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">3</span>) <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"-----------------------------------------------------"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">a</span> <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">20</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"captureByValue() 執行之前,外部作用域變數 a = "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">a</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">auto</span> <span style="color: #abb2bf;">captureByValue</span> <span style="color: #e06c75;">=</span> [<span style="color: #e06c75;">=</span>]() <span style="color: #e06c75;">mutable</span> {<span style="color: #676f7d;"> // 因為 [=] 之故,若去掉 mutable => 錯誤</span></span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">a</span><span style="color: #e06c75;">++</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"captureByValue() 執行之後,函數內區域變數 a = "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">a</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>; </span></div><div><span style="font-size: x-small;"> };</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">captureByValue</span>();</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"captureByValue() 執行之後,外部作用域變數 a = "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">a</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"-----------------------------------------------------"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // [=]:Capture by Value,「依值捕捉」。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // [&]:Capture by Reference,「依參考捕捉」。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // lambda 函數 captureByValue() 採「依值捕捉」(Capture by Value)外部作用域變數 a </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 進行運算,按 C++ lambda Expression 規則,「依值捕捉」變數的方式是不允許在 lambda </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 函數主體中修改變數的,但若加上 mutable 關鍵字修飾,則可打破這項規定;話雖如此,修改效</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 應也僅止於 lambda 函數主體範圍內之區域變數,對於外部作用域原變數值是沒有任何影響的。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">b</span> <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">50</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"captureByReference() 執行之前,外部作用域變數 b = "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">b</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">auto</span> <span style="color: #abb2bf;">captureByReference</span> <span style="color: #e06c75;">=</span> [<span style="color: #e06c75;">&</span>]() {</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">b</span><span style="color: #e06c75;">++</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"captureByReference() 執行之後,函數內區域變數 b = "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">b</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>; </span></div><div><span style="font-size: x-small;"> };</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">captureByReference</span>();</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"captureByReference() 執行之後,外部作用域變數 b = "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">b</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // lambda 函數 captureByReference() 採「依參考捕捉」(Capture by Reference)外部作</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 用域變數 b 進行運算,如此一來,lambda 函數主體會建立一個與外部作用域變數同名的參考,故</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 修改了 lambda 函數主體內的區域變數 b 值,也會同步更改外部變數 b 的值。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">vector</span><span style="color: #e06c75;"><</span><span style="color: #56b6c2;">int</span><span style="color: #e06c75;">></span> <span style="color: #abb2bf;">box</span> {<span style="color: #c678dd;">12</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">24</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">9</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">61</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">43</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">55</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">79</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">35</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">81</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">47</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">6</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">92</span>};</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"-----------------------------------------------------"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>; </span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"box = {12, 24, 9, 61, 43, 55, 79, 35, 81, 47, 6, 92}"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">cnt</span> <span style="color: #e06c75;">=</span> <span style="color: #98c379;">count_if</span>(<span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">begin</span>()<span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">end</span>()<span style="color: #abb2bf;">,</span> [](<span style="color: #56b6c2;">int</span> <span style="color: #d19a66; font-style: italic;">i</span>) -><span style="color: #56b6c2;"> bool </span>{ <span style="color: #e06c75;">return</span> <span style="color: #d19a66; font-style: italic;">i</span><span style="color: #e06c75;">></span><span style="color: #c678dd;">40</span>; });</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"box 元素值 > 40 者,共有:"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">cnt</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" 個"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 上述 count_if() 演算中的 lambda 函數片段 [](int i) -> bool { return i>40; }</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 可以簡化為:[](int i) { return i>40; },其回傳型別可自動被推斷為 bool。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // count_if() 解說,可參考:https://www.geeksforgeeks.org/count_if-in-c/</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 以本例言,第一個參數 box.begin() 為起點;第二個參數 box.end() 為終點,第三個參數為</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // lambda 函數構成的計數條件(當條件為 true => 列入計數)。count_if 執行時,會把 box中</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 所有元素依序一個接著一個以參數傳遞的方式傳入 lambda 函數進行檢測;依此,lambda 函數透</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 過相應的參數列「(int i)」逐次接收單一來自 box 元素值並予以比較運算(i>40),比較結果若</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 為 true => 計數加 1;否則不予計數,如此迭代遍歷 box 之起點至終點。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 參考文件:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://docs.microsoft.com/en-us/cpp/cpp/lambda-expressions-in-cpp?view=msvc-160</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://openhome.cc/Gossip/CppGossip/Lambda.html</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://blog.gtwang.org/programming/lambda-expression-in-c11/</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://liam.page/2017/05/25/the-mutable-keyword-in-Cxx/</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://www.modernescpp.com/index.php/c-insights-lambdas</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://dev.to/delta456/modern-c-lambdas-3pjl</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://en.cppreference.com/w/cpp/algorithm/count</span></span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">執行結果:</span></div><div><span style="font-size: x-small;"><span style="color: #61afef;">Hello</span> Lambda</span></div><div><span style="font-size: x-small;"><span style="color: #98c379;">ldaSum</span>(<span style="color: #c678dd;">1</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">2</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">3</span>) <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">6</span></span></div><div><span style="color: #e06c75;"><span style="font-size: x-small;">-----------------------------------------------------</span></span></div><div><span style="font-size: x-small;"><span style="color: #98c379;">captureByValue</span>() 執行之前,外部作用域變數 a <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">20</span></span></div><div><span style="font-size: x-small;"><span style="color: #98c379;">captureByValue</span>() 執行之後,函數內區域變數 a <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">21</span></span></div><div><span style="font-size: x-small;"><span style="color: #98c379;">captureByValue</span>() 執行之後,外部作用域變數 a <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">20</span></span></div><div><span style="color: #e06c75;"><span style="font-size: x-small;">-----------------------------------------------------</span></span></div><div><span style="font-size: x-small;"><span style="color: #98c379;">captureByReference</span>() 執行之前,外部作用域變數 b <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">50</span></span></div><div><span style="font-size: x-small;"><span style="color: #98c379;">captureByReference</span>() 執行之後,函數內區域變數 b <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">51</span></span></div><div><span style="font-size: x-small;"><span style="color: #98c379;">captureByReference</span>() 執行之後,外部作用域變數 b <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">51</span></span></div><div><span style="color: #e06c75;"><span style="font-size: x-small;">-----------------------------------------------------</span></span></div><div><span style="font-size: x-small;">box <span style="color: #e06c75;">=</span> {<span style="color: #c678dd;">12</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">24</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">9</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">61</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">43</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">55</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">79</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">35</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">81</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">47</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">6</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">92</span>}</span></div><div><span style="font-size: x-small;">box 元素值 <span style="color: #e06c75;">></span> <span style="color: #c678dd;">40</span> 者,共有:<span style="color: #c678dd;">7</span> 個</span></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-69921560506338263512020-11-18T13:57:00.005+08:002020-11-18T13:57:26.431+08:00閒談C++(25):函數指標、成員函數指標<div style="background-color: #282c34; color: #bbbbbb; font-family: "Source Code Pro", Consolas, "Courier New", monospace; line-height: 20px; white-space: pre;"><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><iostream></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">using</span> <span style="color: #56b6c2;">namespace</span> std;</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> <span style="color: #98c379;">test</span>(<span style="color: #56b6c2;">int</span> <span style="color: #d19a66; font-style: italic;">a</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">return</span> <span style="color: #e06c75;">++</span><span style="color: #d19a66; font-style: italic;">a</span>;</span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"><span style="color: #56b6c2;">class</span> <span style="color: #61afef;">app</span> {</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">public</span><span style="color: #abb2bf;">:</span></span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #98c379;">test</span>(<span style="color: #56b6c2;">int</span>);</span></div><div><span style="font-size: x-small;">};</span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> <span style="color: #61afef;">app</span><span style="color: #abb2bf;">::</span><span style="color: #98c379;">test</span>(<span style="color: #56b6c2;">int</span> <span style="color: #d19a66; font-style: italic;">a</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">return</span> <span style="color: #e06c75;">++</span><span style="color: #d19a66; font-style: italic;">a</span>;</span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> <span style="color: #98c379;">main</span>() {</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> (*<span style="color: #abb2bf;">fp</span>)(<span style="color: #56b6c2;">int</span>) <span style="color: #e06c75;">=</span> <span style="color: #98c379;">test</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> (<span style="color: #61afef;">app</span><span style="color: #abb2bf;">::</span><span style="color: #e06c75;">*</span><span style="color: #abb2bf;">mfp</span>)(<span style="color: #56b6c2;">int</span>) <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">&</span><span style="color: #61afef;">app</span><span style="color: #abb2bf;">::</span><span style="color: #98c379;">test</span>; </span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ------------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 一般函數指標及成員函數指標可參考:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://openhome.cc/Gossip/CppGossip/MemberPtr.html</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // http://umich.edu/~eecs381/handouts/Pointers_to_memberfuncs.pdf</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 以下為摘要:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 一般函數指標之宣告、設定及調用:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 1. return_type (*pointer_name)(parameter types)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 2. pointer_name = function_name 或 pointer_name = &function_name</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 3. result = pointer_name(arguments)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // <註>:1,2 可合併成一道敘述</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> //</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 成員函數指標之宣告、設定及調用:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 1. return_type (class_name::*pointer_name)(parameter types)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 2. pointer_name = &class_name::member_function_name</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 3. result = (object.*pointer_name)(arguments) 或</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // result = (object_ptr->*pointer_name)(arguments)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // <註>:1,2 可合併成一道敘述</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ------------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">app</span> <span style="color: #abb2bf;">appobj1</span>;<span style="color: #676f7d;"> // 物件存取成員使用「.」</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">app</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">appobj2</span> <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">new</span> <span style="color: #61afef;">app</span>();<span style="color: #676f7d;"> // 物件指標存取成員使用「->」</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"一般函數指標 fp 所在位址:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">fp</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" , fp(2) = "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">fp</span>(<span style="color: #c678dd;">2</span>) <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"成員函數指標 mfp 所在位址:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">mfp</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" , (appobj1.*mfp)(3) = "</span> </span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;"><<</span> (<span style="color: #abb2bf;">appobj1</span><span style="color: #abb2bf;">.*</span><span style="color: #abb2bf;">mfp</span>)(<span style="color: #c678dd;">3</span>) <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"成員函數指標 mfp 所在位址:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">mfp</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" , (appobj2->*mfp)(3) = "</span> </span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;"><<</span> (<span style="color: #abb2bf;">appobj2</span><span style="color: #abb2bf;">->*</span><span style="color: #abb2bf;">mfp</span>)(<span style="color: #c678dd;">3</span>) <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">執行結果:</span></div><div><span style="font-size: x-small;"><span style="color: #61afef;">一般函數指標</span> fp 所在位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fe30</span> <span style="color: #abb2bf;">,</span> <span style="color: #98c379;">fp</span>(<span style="color: #c678dd;">2</span>) <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">3</span></span></div><div><span style="font-size: x-small;">成員函數指標 mfp 所在位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fe20</span> <span style="color: #abb2bf;">,</span> (<span style="color: #61afef;">appobj1</span><span style="color: #abb2bf;">.*mfp</span>)(<span style="color: #c678dd;">3</span>) <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">4</span></span></div><div><span style="font-size: x-small;">成員函數指標 mfp 所在位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fe20</span> <span style="color: #abb2bf;">,</span> (<span style="color: #61afef;">appobj2</span><span style="color: #abb2bf;">->*mfp</span>)(<span style="color: #c678dd;">3</span>) <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">4</span></span></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-27102055528160827712020-11-16T20:42:00.006+08:002020-11-17T22:22:50.541+08:00閒談C++(24):連結串列 (Linked List) - 使用 shared_ptr 智慧型指標<div style="background-color: #282c34; color: #bbbbbb; font-family: "Source Code Pro", Consolas, "Courier New", monospace; line-height: 20px; white-space: pre;"><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><string></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><iostream></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><memory></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">using</span> <span style="color: #56b6c2;">namespace</span> std;</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"><span style="color: #56b6c2;">class</span> <span style="color: #61afef;">Node</span></span></div><div><span style="font-size: x-small;">{</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">public</span><span style="color: #abb2bf;">:</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">string</span> <span style="color: #abb2bf;">id</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">string</span> <span style="color: #abb2bf;">name</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">shared_ptr</span><span style="color: #e06c75;"><</span><span style="color: #61afef;">Node</span><span style="color: #e06c75;">></span> <span style="color: #abb2bf;">next</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // id, name, next 為資料成員</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 使用 shared_ptr 智慧型指標,在觀念理解上,可以看做:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 以「shared_ptr<型別> ptr」 取代了 「型別* ptr」之原始指標,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // EX:shared_ptr<Node> next 取代了 Node* next</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">Node</span>(<span style="color: #61afef;">string</span> <span style="color: #d19a66; font-style: italic;">id</span><span style="color: #abb2bf;">,</span> <span style="color: #61afef;">string</span> <span style="color: #d19a66; font-style: italic;">name</span><span style="color: #abb2bf;">,</span> <span style="color: #61afef;">shared_ptr</span><<span style="color: #61afef;">Node</span>> <span style="color: #d19a66; font-style: italic;">next</span>)<span style="color: #abb2bf;">:</span></span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">id</span>(<span style="color: #d19a66; font-style: italic;">id</span>)<span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">name</span>(<span style="color: #d19a66; font-style: italic;">name</span>)<span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">next</span>(<span style="color: #d19a66; font-style: italic;">next</span>) {};</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">~Node</span>(); </span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">void</span> <span style="color: #98c379;">showInfo</span>();</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // Node(...)為建構式,利用「建構式成員初始化清單」將資料成員予以初始化</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // Constructors and member initializer lists:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://en.cppreference.com/w/cpp/language/constructor</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ~Node()為解構式(Destructor),當物件被銷毀(離開作用域或程式結束),</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 此解構式自動被呼叫,因使用智慧型指標,記憶體回收由系統自動處理.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // --------------------------------------------------------- </span></span></div><div><span style="font-size: x-small;">};</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;">//-------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;">// 以下透過「::」範圍解析運算子定義解構式 ~Node()及成員函數 showInfo()</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;">//-------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"><span style="color: #61afef;">Node</span><span style="color: #abb2bf;">::</span><span style="color: #98c379;">~</span><span style="color: #98c379;">Node</span>() {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">this</span><span style="color: #abb2bf;">-></span><span style="color: #abb2bf;">name</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"-動態配置被回收.."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;">} </span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;">//</span></span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">void</span> <span style="color: #61afef;">Node</span><span style="color: #abb2bf;">::</span><span style="color: #98c379;">showInfo</span>() {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"id:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">this</span><span style="color: #abb2bf;">-></span><span style="color: #abb2bf;">id</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"/"</span></span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"name:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">this</span><span style="color: #abb2bf;">-></span><span style="color: #abb2bf;">name</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"/"</span></span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"當前節點位址(this):"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">this</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"/"</span></span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"下一節點位址(this->next):"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">this</span><span style="color: #abb2bf;">-></span><span style="color: #abb2bf;">next</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"id:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">this</span><span style="color: #abb2bf;">-></span><span style="color: #abb2bf;">id</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" => 位址:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span>(<span style="color: #e06c75;">this</span><span style="color: #abb2bf;">-></span><span style="color: #abb2bf;">id</span>) </span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"/name:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">this</span><span style="color: #abb2bf;">-></span><span style="color: #abb2bf;">name</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" => 位址:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span>(<span style="color: #e06c75;">this</span><span style="color: #abb2bf;">-></span><span style="color: #abb2bf;">name</span>)</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------</span></span></div><div><div style="line-height: 20px;"><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // this 是一個指標,而且隱含於類別成員函數之中. this 指向調用該成員函數之</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 物件自身,也就是該物件本身資料成員區塊在記憶體中的位址。若以類別衍生多個</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 物件言,不同物件各自擁有一份資料成員;然成員函數也就僅僅一份。至於同樣一</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 份成員函數又如何處理多份物件各自擁有的資料成員呢?答案就是「this」指標。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 緣此,當一個物件調用其成員函數時,編譯器會將目前該物件資料成員所在的記憶</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 體位址隱式地傳遞給成員函數中的 this 指標,當此,成員函數中的 this 指標</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 即指向該物件。簡言之,this 指標隱含於成員函數中,它用來指向調用它的物件。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 參考:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://openhome.cc/Gossip/CppGossip/thisPointer.html</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://www.bogotobogo.com/cplusplus/this_pointer.php</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://docs.microsoft.com/zh-tw/cpp/cpp/this-pointer?view=msvc-160</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // PS:資料成員 (data member)、成員函數 (member function)</span></span></div></div></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;">}</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;">//-------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> <span style="color: #98c379;">main</span>()</span></div><div><span style="font-size: x-small;">{</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">shared_ptr</span><span style="color: #e06c75;"><</span><span style="color: #61afef;">Node</span><span style="color: #e06c75;">></span> <span style="color: #abb2bf;">root</span> <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">shared_ptr</span><span style="color: #e06c75;"><</span><span style="color: #61afef;">Node</span><span style="color: #e06c75;">></span> <span style="color: #abb2bf;">current</span> <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">shared_ptr</span><span style="color: #e06c75;"><</span><span style="color: #61afef;">Node</span><span style="color: #e06c75;">></span> <span style="color: #abb2bf;">move</span> <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span>; </span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // root, current, move 同為指向 Node 類別的指標變數,且初始化為 nullptr,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 進一步說,root, current, move 指標變數內容存放「所指向之Node 物件在記憶</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 體中的位址」,換句話說, root 本身內容是記憶體位址,而 *root 為該記憶體位</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 址所定址到的 Node 物件,這就是所謂的「依址取值」,也是一種間接定址法。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">string</span> <span style="color: #abb2bf;">getID</span><span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">getName</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"建立連結串列(id:2位數字,名字:自訂) 'exit' 離開..."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"請輸入id:"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">getline</span>(<span style="color: #61afef;">cin</span><span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">getID</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"節點名字:"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">getline</span>(<span style="color: #61afef;">cin</span><span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">getName</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">root</span> <span style="color: #98c379;">=</span> <span style="color: #98c379;">make_shared</span><<span style="color: #61afef;">Node</span>>(<span style="color: #abb2bf;">getID</span><span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">getName</span><span style="color: #abb2bf;">,</span> <span style="color: #56b6c2;">nullptr</span>);<span style="color: #676f7d;"> // 調用建構式初始化</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ----------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // root 是 Linked List 的起始節點,後續新生節點依序往後串接,串接動作則是透</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 過 Node 類別中的資料成員 next,而 next 宣告為「shared_ptr<Node> next」</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 代表為一個指向 Node 類別的指標。換言之, next 指標變數存放「所指向之 Node</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 物件在記憶體中的位址」。如此一來,各自已生成的 Node 節點之 next 指標便能維</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 護(存放)其後續新生節點所在的記憶體位址,這種透過記憶體位址前後有序互相參照且</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 彼此串聯的結構,就是所謂的 Linked List (連結串列)。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 關於智慧型指標,最安全的配置及使用動態記憶體的方法是調用 make_shared 標準庫</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 函數,此函數在動態記憶體中配置一個對象並進行初始化。Smart Pointer 使用前要</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // #include <memory></span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">current</span> <span style="color: #98c379;">=</span> <span style="color: #abb2bf;">root</span>;<span style="color: #676f7d;"> // 一開始,只有 root 被建立, 設定好起點,開始要往後串接了.</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">do</span></span></div><div><span style="font-size: x-small;"> {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"請輸入id:"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">getline</span>(<span style="color: #61afef;">cin</span><span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">getID</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"節點名字:"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">getline</span>(<span style="color: #61afef;">cin</span><span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">getName</span>);</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> //-------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">if</span> (<span style="color: #abb2bf;">getID</span> <span style="color: #98c379;">==</span> <span style="color: #e5c07b;">"exit"</span> <span style="color: #e06c75;">||</span> <span style="color: #abb2bf;">getName</span> <span style="color: #98c379;">==</span> <span style="color: #e5c07b;">"exit"</span>)</span></div><div><span style="font-size: x-small;"> {</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">break</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">move</span> <span style="color: #98c379;">=</span> <span style="color: #98c379;">make_shared</span><<span style="color: #61afef;">Node</span>>(<span style="color: #abb2bf;">getID</span><span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">getName</span><span style="color: #abb2bf;">,</span> <span style="color: #56b6c2;">nullptr</span>);<span style="color: #676f7d;"> // 調用建構式初始化</span></span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">current</span><span style="color: #98c379;">-></span><span style="color: #abb2bf;">next</span> <span style="color: #98c379;">=</span> <span style="color: #abb2bf;">move</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">current</span> <span style="color: #98c379;">=</span> <span style="color: #abb2bf;">move</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">current</span><span style="color: #98c379;">-></span><span style="color: #abb2bf;">next</span> <span style="color: #98c379;">=</span> <span style="color: #56b6c2;">nullptr</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">while</span> (<span style="color: #56b6c2;">true</span>);</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // --------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // <解析>:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // root:固定指向連結串列的起點(Header).</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // current:指向當前連結串列最後一個節點.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // move:動態產生新的節點.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // current->next = move:目前串列最後一個節點的 next 指標設定為新生節點,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 這個作用以記憶體層次來說就是:目前串列最後一個節點的 next 指標內容設定為</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 新生節點所在的記憶體位址。如此一來就能夠把 current 往後串上 move 了...</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 還記得嗎?「current:指向當前串列最後一個節點」,因此,為保持這樣的結構,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // => current = move => current 終於又指向了串列最後一個節點了..</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ※※※ 記得指標的意義:指標變數是用來存放變數或物件在記憶體中的位址。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 指標變數存放的是記憶體位址,而不是值(很重要!!!)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // current 所存內容是記憶體位址; *current 才是值(本範例為一個物件實例)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 最後 current->next = nullptr => 避免懸空指標,更註記了連結串列的結尾.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // --------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"連結串列各節點(仔細觀察當前節點及下一節點的位址變化):"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"--------------------------------------------"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">current</span> <span style="color: #98c379;">=</span> <span style="color: #abb2bf;">root</span>;<span style="color: #676f7d;"> // 連結串列走訪前將 current 指向 root 起點</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> //</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">while</span> (<span style="color: #abb2bf;">current</span> <span style="color: #98c379;">!=</span> <span style="color: #56b6c2;">nullptr</span>)</span></div><div><span style="font-size: x-small;"> {</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">current</span><span style="color: #98c379;">-></span><span style="color: #98c379;">showInfo</span>();</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"當前節點所在記憶體位址:&(*current) => "</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span>(<span style="color: #98c379;">*</span><span style="color: #abb2bf;">current</span>) <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>; </span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"當前節點的 name:(*current).name => "</span> <span style="color: #98c379;"><<</span> (<span style="color: #98c379;">*</span><span style="color: #abb2bf;">current</span>)<span style="color: #abb2bf;">.</span><span style="color: #abb2bf;">name</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">current</span> <span style="color: #98c379;">=</span> <span style="color: #abb2bf;">current</span><span style="color: #98c379;">-></span><span style="color: #abb2bf;">next</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // --------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // *current 指向當前走訪的節點物件,但無法利用 cout << *current </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 來檢視節點物件內容,因為 *current 指向一塊記憶體空間配置,但可以加</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 上取址(&)運算成為 &(*current) ,藉此觀察記憶位址變化...</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // (*current).name 等價於 current->name</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // --------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> } </span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 走訪過程:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 1. 設定由 root 起點開始 => current = root, current 依各節點 next</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 指標之串接,動態移位以完成循序走訪.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 2. 判斷當前 current 是否為 nullptr, 若是 => 已到串列尾,結束.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 否則重複走訪,走訪期間輸出節點資訊.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 3. 利用 current = current->next 將走訪移位至下一個節點.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -----------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"連結串列節點全部輸出 OK.."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">system</span>(<span style="color: #e5c07b;">"PAUSE"</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">return</span> <span style="color: #98c379;">EXIT_SUCCESS</span>;</span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">執行結果:</span></div><div><span style="font-size: x-small;"><span style="color: #61afef;">建立連結串列</span>(id:<span style="color: #c678dd;">2</span>位數字,名字:自訂) <span style="color: #e5c07b;">'exit'</span> 離開...</span></div><div><span style="font-size: x-small;">請輸入id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">1</span></span></div><div><span style="font-size: x-small;">節點名字:C</span></div><div><span style="font-size: x-small;">請輸入id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">2</span></span></div><div><span style="font-size: x-small;">節點名字:Python</span></div><div><span style="font-size: x-small;">請輸入id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">3</span></span></div><div><span style="font-size: x-small;">節點名字:Java</span></div><div><span style="font-size: x-small;">請輸入id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">4</span></span></div><div><span style="font-size: x-small;">節點名字:C<span style="color: #e06c75;">++</span></span></div><div><span style="font-size: x-small;">請輸入id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">5</span></span></div><div><span style="font-size: x-small;">節點名字:C#</span></div><div><span style="font-size: x-small;">請輸入id:exit</span></div><div><span style="font-size: x-small;">節點名字:</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">連結串列各節點(仔細觀察當前節點及下一節點的位址變化):</span></div><div><span style="color: #e06c75;"><span style="font-size: x-small;">--------------------------------------------</span></span></div><div><span style="font-size: x-small;">id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">1</span>/name:C/當前節點位址(<span style="color: #e06c75;">this</span>):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531d50</span>/下一節點位址(<span style="color: #e06c75;">this</span><span style="color: #abb2bf;">->next</span>):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531dc0</span></span></div><div><span style="font-size: x-small;">id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">1</span> <span style="color: #e06c75;">=></span> 位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531d50</span>/name:C <span style="color: #e06c75;">=></span> 位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531d70</span></span></div><div><span style="font-size: x-small;">當前節點所在記憶體位址:<span style="color: #e06c75;">&</span>(<span style="color: #e06c75;">*</span>current) <span style="color: #e06c75;">=></span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531d50</span></span></div><div><span style="font-size: x-small;">當前節點的 name:(<span style="color: #e06c75;">*</span>current)<span style="color: #abb2bf;">.name</span> <span style="color: #e06c75;">=></span> C</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">2</span>/name:Python/當前節點位址(<span style="color: #e06c75;">this</span>):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531dc0</span>/下一節點位址(<span style="color: #e06c75;">this</span><span style="color: #abb2bf;">->next</span>):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531e30</span></span></div><div><span style="font-size: x-small;">id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">2</span> <span style="color: #e06c75;">=></span> 位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531dc0</span>/name:Python <span style="color: #e06c75;">=></span> 位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531de0</span></span></div><div><span style="font-size: x-small;">當前節點所在記憶體位址:<span style="color: #e06c75;">&</span>(<span style="color: #e06c75;">*</span>current) <span style="color: #e06c75;">=></span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531dc0</span></span></div><div><span style="font-size: x-small;">當前節點的 name:(<span style="color: #e06c75;">*</span>current)<span style="color: #abb2bf;">.name</span> <span style="color: #e06c75;">=></span> Python</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">3</span>/name:Java/當前節點位址(<span style="color: #e06c75;">this</span>):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531e30</span>/下一節點位址(<span style="color: #e06c75;">this</span><span style="color: #abb2bf;">->next</span>):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531ea0</span></span></div><div><span style="font-size: x-small;">id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">3</span> <span style="color: #e06c75;">=></span> 位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531e30</span>/name:Java <span style="color: #e06c75;">=></span> 位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531e50</span></span></div><div><span style="font-size: x-small;">當前節點所在記憶體位址:<span style="color: #e06c75;">&</span>(<span style="color: #e06c75;">*</span>current) <span style="color: #e06c75;">=></span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531e30</span></span></div><div><span style="font-size: x-small;">當前節點的 name:(<span style="color: #e06c75;">*</span>current)<span style="color: #abb2bf;">.name</span> <span style="color: #e06c75;">=></span> Java</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">4</span>/name:C<span style="color: #e06c75;">++</span>/當前節點位址(<span style="color: #e06c75;">this</span>):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531ea0</span>/下一節點位址(<span style="color: #e06c75;">this</span><span style="color: #abb2bf;">->next</span>):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531f10</span></span></div><div><span style="font-size: x-small;">id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">4</span> <span style="color: #e06c75;">=></span> 位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531ea0</span>/name:C<span style="color: #e06c75;">++</span> <span style="color: #e06c75;">=></span> 位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531ec0</span></span></div><div><span style="font-size: x-small;">當前節點所在記憶體位址:<span style="color: #e06c75;">&</span>(<span style="color: #e06c75;">*</span>current) <span style="color: #e06c75;">=></span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531ea0</span></span></div><div><span style="font-size: x-small;">當前節點的 name:(<span style="color: #e06c75;">*</span>current)<span style="color: #abb2bf;">.name</span> <span style="color: #e06c75;">=></span> C<span style="color: #e06c75;">++</span></span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">5</span>/name:C#/當前節點位址(<span style="color: #e06c75;">this</span>):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531f10</span>/下一節點位址(<span style="color: #e06c75;">this</span><span style="color: #abb2bf;">->next</span>):<span style="color: #c678dd;">0</span></span></div><div><span style="font-size: x-small;">id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">5</span> <span style="color: #e06c75;">=></span> 位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531f10</span>/name:C# <span style="color: #e06c75;">=></span> 位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531f30</span></span></div><div><span style="font-size: x-small;">當前節點所在記憶體位址:<span style="color: #e06c75;">&</span>(<span style="color: #e06c75;">*</span>current) <span style="color: #e06c75;">=></span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531f10</span></span></div><div><span style="font-size: x-small;">當前節點的 name:(<span style="color: #e06c75;">*</span>current)<span style="color: #abb2bf;">.name</span> <span style="color: #e06c75;">=></span> C#</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">連結串列節點全部輸出 OK..</span></div><div><span style="font-size: x-small;">請按任意鍵繼續 . . .</span></div><div><span style="font-size: x-small;">C<span style="color: #e06c75;">-</span>動態配置被回收..</span></div><div><span style="font-size: x-small;">Python<span style="color: #e06c75;">-</span>動態配置被回收..</span></div><div><span style="font-size: x-small;">Java<span style="color: #e06c75;">-</span>動態配置被回收..</span></div><div><span style="font-size: x-small;">C<span style="color: #e06c75;">++-</span>動態配置被回收..</span></div><div><span style="font-size: x-small;">C#<span style="color: #e06c75;">-</span>動態配置被回收..</span></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-9201533423536997062020-11-15T20:39:00.005+08:002020-11-15T21:00:33.594+08:00閒談C++(23):淺說 Smart Pointer 智慧型指標之 shared_ptr<div style="background-color: #282c34; color: #bbbbbb; font-family: "Source Code Pro", Consolas, "Courier New", monospace; line-height: 20px; white-space: pre;"><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><iostream></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><memory></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">using</span> <span style="color: #56b6c2;">namespace</span> std;</span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> <span style="color: #98c379;">main</span>() {</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> //</span></span></div><div><span style="font-size: x-small;"> shared_ptr<span style="color: #e06c75;"><</span><span style="color: #56b6c2;">int</span><span style="color: #e06c75;">></span> n;<span style="color: #676f7d;"> // n 為指向 int 的指標,初始化為 nullptr</span></span></div><div><span style="font-size: x-small;"> shared_ptr<span style="color: #e06c75;"><</span><span style="color: #56b6c2;">int</span><span style="color: #e06c75;">></span> p <span style="color: #e06c75;">=</span> <span style="color: #98c379;">make_shared</span><<span style="color: #56b6c2;">int</span>>();</span></div><div><span style="font-size: x-small;"> shared_ptr<span style="color: #e06c75;"><</span><span style="color: #56b6c2;">int</span><span style="color: #e06c75;">></span> q <span style="color: #e06c75;">=</span> <span style="color: #98c379;">make_shared</span><<span style="color: #56b6c2;">int</span>>(<span style="color: #c678dd;">25</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">if</span> (n <span style="color: #e06c75;">==</span> <span style="color: #56b6c2;">nullptr</span>) {</span></div><div><span style="font-size: x-small;"> cout <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">"n = nullptr"</span> <span style="color: #e06c75;"><<</span> endl;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;"> cout <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">"p = "</span> <span style="color: #e06c75;"><<</span> p <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">" , *p = "</span> <span style="color: #e06c75;"><<</span> <span style="color: #e06c75;">*</span>p <span style="color: #e06c75;"><<</span> endl;</span></div><div><span style="font-size: x-small;"> cout <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">"q = "</span> <span style="color: #e06c75;"><<</span> q <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">" , *q = "</span> <span style="color: #e06c75;"><<</span> <span style="color: #e06c75;">*</span>q <span style="color: #e06c75;"><<</span> endl;</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">auto</span> <span style="color: #98c379;">r</span>(q);</span></div><div><span style="font-size: x-small;"> cout <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">"經過 auto r(q) 複製後.."</span> <span style="color: #e06c75;"><<</span> endl;</span></div><div><span style="font-size: x-small;"> cout <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">"r = "</span> <span style="color: #e06c75;"><<</span> r <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">" , *r = "</span> <span style="color: #e06c75;"><<</span> <span style="color: #e06c75;">*</span>r <span style="color: #e06c75;"><<</span> endl;</span></div><div><span style="font-size: x-small;"> cout <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">"....."</span> <span style="color: #e06c75;"><<</span> endl;</span></div><div><span style="font-size: x-small;"> shared_ptr<span style="color: #e06c75;"><</span><span style="color: #56b6c2;">int</span><span style="color: #e06c75;">></span> s <span style="color: #e06c75;">=</span> <span style="color: #98c379;">make_shared</span><<span style="color: #56b6c2;">int</span>>(<span style="color: #c678dd;">50</span>);</span></div><div><span style="font-size: x-small;"> cout <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">"s = "</span> <span style="color: #e06c75;"><<</span> s <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">" , *s = "</span> <span style="color: #e06c75;"><<</span> <span style="color: #e06c75;">*</span>s <span style="color: #e06c75;"><<</span> endl;</span></div><div><span style="font-size: x-small;"> s <span style="color: #e06c75;">=</span> q; </span></div><div><span style="font-size: x-small;"> cout <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">"經過 s = q 賦值後.."</span> <span style="color: #e06c75;"><<</span> endl;</span></div><div><span style="font-size: x-small;"> cout <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">"s = "</span> <span style="color: #e06c75;"><<</span> s <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">" , *s = "</span> <span style="color: #e06c75;"><<</span> <span style="color: #e06c75;">*</span>s <span style="color: #e06c75;"><<</span> endl;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">*</span>s <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">100</span>;</span></div><div><span style="font-size: x-small;"> cout <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">"經過 *s = 100 敘述後.."</span> <span style="color: #e06c75;"><<</span> endl;</span></div><div><span style="font-size: x-small;"> cout <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">"r = "</span> <span style="color: #e06c75;"><<</span> r <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">" , *r = "</span> <span style="color: #e06c75;"><<</span> <span style="color: #e06c75;">*</span>r <span style="color: #e06c75;"><<</span> endl;</span></div><div><span style="font-size: x-small;"> cout <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">"q = "</span> <span style="color: #e06c75;"><<</span> q <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">" , *q = "</span> <span style="color: #e06c75;"><<</span> <span style="color: #e06c75;">*</span>q <span style="color: #e06c75;"><<</span> endl;</span></div><div><span style="font-size: x-small;"> cout <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">"與 q 共享動態配置的指標數量:"</span> <span style="color: #e06c75;"><<</span> <span style="color: #61afef;">q</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">use_count</span>() <span style="color: #e06c75;"><<</span> endl;</span></div><div><span style="font-size: x-small;"> cout <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">"與 p 共享動態配置的指標數量:"</span> <span style="color: #e06c75;"><<</span> <span style="color: #61afef;">p</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">use_count</span>() <span style="color: #e06c75;"><<</span> endl;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ----------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 使用 Smart Pointer ,必須指定想要創建對象的型別,定義的方式</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 與使用模板(Template) 相同。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 基於 Smart Pointer, 最安全的配置及使用動態記憶體的方法是調用</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // make_shared 標準庫函數,此函數在動態記憶體中配置一個對象並進</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 行初始化。 Smart Pointer 使用前要 #include <memory></span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ----------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // auto r(q) => r 是 q 的複製(指標的複製),r 同 q 指向同一物</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 件,此結果為遞增 q 中的參考計數(reference count).</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // s = q => s 賦值為 q。 => 遞增 q 的參考計數;遞減 s 的參考</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 計數. 若 s 的參考計數為 0 => 釋放原本 s 指向的動態配置(解構)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ----------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // C++11 以後提供了 Smart Pointer,用來自動管理記憶體的配置與</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 回收,相較原始指標於動態記憶體配置使用 new 及 delete,可避免</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 因人為疏失而造成的記憶體洩漏或懸空指標等問題。Smart Pointer</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 或翻譯成「智慧型指標」,主要有 shared_ptr、unique_ptr、</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // weak_ptr 等.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // PS:shared_ptr 支援複製及賦值,但若為 unique_ptr 則不支援</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 複製與賦值.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ----------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // <補充>:unique_ptr</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ----------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // unique_ptr<int> x(new int(12));</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // unique_ptr<int> y(new int(24));</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // cout << *x << " , " << *y << endl;</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // x = y; => 錯誤,因為不支援一般賦值</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // auto z(x); => 錯誤,因為不支援一般複製</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // unique_ptr 不像 shared_ptr 有 make_shared 標準庫函數可用,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 因此定義 unique_ptr 時,必需綁定到一個以 new 返回的指標上,而</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 且必需採用直接初始化的形式. unique_ptr 不支援一般的複製及賦值.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 直接初始化(Direct initialization):</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://en.cppreference.com/w/cpp/language/direct_initialization</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ------------------------------------------------------</span></span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">執行結果:</span></div><div><span style="font-size: x-small;">n <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span></span></div><div><span style="font-size: x-small;">p <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">6319e0</span> <span style="color: #abb2bf;">,</span> <span style="color: #e06c75;">*</span>p <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">0</span></span></div><div><span style="font-size: x-small;">q <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">631a00</span> <span style="color: #abb2bf;">,</span> <span style="color: #e06c75;">*</span>q <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">25</span></span></div><div><span style="font-size: x-small;">經過 <span style="color: #56b6c2;">auto</span> <span style="color: #98c379;">r</span>(q) 複製後..</span></div><div><span style="font-size: x-small;">r <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">631a00</span> <span style="color: #abb2bf;">,</span> <span style="color: #e06c75;">*</span>r <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">25</span></span></div><div><span style="font-size: x-small;">.....</span></div><div><span style="font-size: x-small;">s <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">631d50</span> <span style="color: #abb2bf;">,</span> <span style="color: #e06c75;">*</span>s <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">50</span></span></div><div><span style="font-size: x-small;">經過 s <span style="color: #e06c75;">=</span> q 賦值後..</span></div><div><span style="font-size: x-small;">s <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">631a00</span> <span style="color: #abb2bf;">,</span> <span style="color: #e06c75;">*</span>s <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">25</span></span></div><div><span style="font-size: x-small;">經過 <span style="color: #e06c75;">*</span>s <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">100</span> 敘述後..</span></div><div><span style="font-size: x-small;">r <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">631a00</span> <span style="color: #abb2bf;">,</span> <span style="color: #e06c75;">*</span>r <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">100</span></span></div><div><span style="font-size: x-small;">q <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">631a00</span> <span style="color: #abb2bf;">,</span> <span style="color: #e06c75;">*</span>q <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">100</span></span></div><div><span style="font-size: x-small;">與 q 共享動態配置的指標數量:<span style="color: #c678dd;">3</span></span></div><div><span style="font-size: x-small;">與 p 共享動態配置的指標數量:<span style="color: #c678dd;">1</span></span></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-70153714438279686292020-11-15T08:42:00.005+08:002020-11-15T16:58:28.484+08:00閒談C++(22):指標、lvalue reference(&) 及 rvalue reference(&&)<div style="background-color: #282c34; color: #bbbbbb; font-family: "Source Code Pro", Consolas, "Courier New", monospace; line-height: 20px; white-space: pre;"><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><iostream></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">using</span> <span style="color: #56b6c2;">namespace</span> std;</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> <span style="color: #98c379;">main</span>() {</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">a</span> <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">20</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">p</span> <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">a</span>; </span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">b</span> <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">a</span>; </span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // int *p = &a,定義指標(Pointer)。指標變數 p 內容值 = a 變數在</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 記憶體中的位址。int &b = a,定義參考(Reference)。b 為 a 的別</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 名(Alias),b 相當 a 的分身,這種參考可視為 lvalue reference</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"初始化..."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"int a = 20"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"int *p = &a"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"int &b = a"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"a = "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">a</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"&a = "</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">a</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"&b = "</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">b</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"p = "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">p</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;<span style="color: #676f7d;"> // 指標變數 p 的內容 = a 變數在記憶體中的位址</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"*p = "</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">p</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;<span style="color: #676f7d;"> // 指標變數 p 所指向的內容</span></span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">b</span> <span style="color: #e06c75;">+=</span> <span style="color: #c678dd;">10</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"b += 10 執行後..."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"a = "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">a</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;<span style="color: #676f7d;"> // b 值改變後,觀察 a 值的變化</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"&a = "</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">a</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"&b = "</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">b</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"p = "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">p</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"*p = "</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">p</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"*&a = "</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">*&</span><span style="color: #abb2bf;">a</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>; </span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // &a 先取得 a 在記憶體中的位址;再以此位址利用解參考(*)運算取得 a 值</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // *&a 等價於 *p ,因為 p 本身的內容值就是 &a</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 「*」:Dereference,翻譯有多種,解參考,提取運算,反參考,間接取值</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 運算等等.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 參考文件:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://openhome.cc/Gossip/CppGossip/Pointer.html</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://zh.wikipedia.org/wiki/指標_(電腦科學)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://docs.microsoft.com/zh-tw/cpp/c-language/indirection-and-address-of-operators?view=msvc-160</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">x</span> <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">2</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">y</span> <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">3</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">z1</span> <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">x</span> <span style="color: #e06c75;">+</span> <span style="color: #abb2bf;">y</span>; </span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #e06c75;">&&</span><span style="color: #abb2bf;">z2</span> <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">x</span> <span style="color: #e06c75;">+</span> <span style="color: #abb2bf;">y</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // --------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 以下為 lvalue, rvalue 粗淺的說明:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 複製(copy) => 兩份相同記憶體內容,執行複製轉存耗時,佔用空間.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 參考(reference) => 同指一份記憶體空間,無需複製轉存,省空間,效率</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 高。尤其面向大量資料(如陣列或物件).</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // z1 = x+y => 將 x+y 的值(記憶空間暫時值)複製給 z1,此時 z1 可視</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 為 lvalue(通常有變數或物件名稱、可以被取址),又 x+y 結果只是一個</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 暫時存放在記憶體空間的值,可視為 rvalue,基本上是沒有名稱的物件(或</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 暫放暫存器,或快取記憶體,或記憶體),離開了當下敘述也就被摧毀了?被</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 摧毀?那為何可以正確地顯示 z1 的值呢?答案是:因為在 z1 = x + y</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 這敘述後,x+y 的值已經複製(copy)一份給 z1 ,因此得以保留。而 z1</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 是一種可以被取址的 lvalue。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 上述,是在 C++11 之前對 lvalue 及 rvalue 粗淺的說明,也就是說,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 在 C++11 之前,rvalue 是無法被 reference 到的,除非透過上述把</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // rvalue 的值複製給變數或物件予以保留下來。而今在 C++11 引入了一個</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // rvalue reference 功能,能夠 reference 到上例 x+y 運算結果之</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 記憶空間,利用 &&:rvalue 參考(rvalue reference), </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // => int &&z2 = x + y</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // --------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 參考文件:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://openhome.cc/Gossip/CppGossip/RvalueReference.html</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------- </span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"z1 = "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">z1</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" , &z1 = "</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">z1</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"z2 = "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">z2</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" , &z2 = "</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">z2</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">string</span> <span style="color: #abb2bf;">s1</span> <span style="color: #e06c75;">=</span> <span style="color: #e5c07b;">"Hello, "</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">string</span> <span style="color: #abb2bf;">s2</span> <span style="color: #e06c75;">=</span> <span style="color: #e5c07b;">"World !"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">string</span> <span style="color: #e06c75;">&&</span><span style="color: #abb2bf;">s3</span> <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">s1</span> <span style="color: #98c379;">+</span> <span style="color: #abb2bf;">s2</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"s3 = "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">s3</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" , &s3 = "</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">s3</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // string &&s3 = s1 + s2 : 並非把 s1+s2 的結果值複製給 s3, 而是</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 執行 rvalue reference => s3 直接 reference 到 s1+s2 運算結果</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 之記憶空間.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------------</span></span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">執行結果:</span></div><div><span style="font-size: x-small;"><span style="color: #61afef;">初始化</span>...</span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> a <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">20</span></span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> <span style="color: #e06c75;">*</span>p <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">&</span>a</span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> <span style="color: #e06c75;">&</span>b <span style="color: #e06c75;">=</span> a</span></div><div><span style="font-size: x-small;">a <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">20</span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">&</span>a <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fde4</span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">&</span>b <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fde4</span></span></div><div><span style="font-size: x-small;">p <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fde4</span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">*</span>p <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">20</span></span></div><div><span style="font-size: x-small;">b <span style="color: #e06c75;">+=</span> <span style="color: #c678dd;">10</span> 執行後...</span></div><div><span style="font-size: x-small;">a <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">30</span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">&</span>a <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fde4</span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">&</span>b <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fde4</span></span></div><div><span style="font-size: x-small;">p <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fde4</span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">*</span>p <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">30</span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">*&</span>a <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">30</span></span></div><div><span style="font-size: x-small;">z1 <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">5</span> <span style="color: #abb2bf;">,</span> <span style="color: #e06c75;">&</span>z1 <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fde0</span></span></div><div><span style="font-size: x-small;">z2 <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">5</span> <span style="color: #abb2bf;">,</span> <span style="color: #e06c75;">&</span>z2 <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fde8</span></span></div><div><span style="font-size: x-small;">s3 <span style="color: #e06c75;">=</span> Hello<span style="color: #abb2bf;">,</span> World <span style="color: #e06c75;">!</span> <span style="color: #abb2bf;">,</span> <span style="color: #e06c75;">&</span>s3 <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fdf0</span></span></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-80478113355644868612020-11-14T09:55:00.014+08:002020-11-17T22:22:01.526+08:00閒談C++(21):Linked List 連結串列 - 再談指標(建構式、解構式及 this 指標)<div style="background-color: #282c34; color: #bbbbbb; font-family: "Source Code Pro", Consolas, "Courier New", monospace; line-height: 20px; white-space: pre;"><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><string></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><iostream></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">using</span> <span style="color: #56b6c2;">namespace</span> std;</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"><span style="color: #56b6c2;">class</span> <span style="color: #61afef;">Node</span></span></div><div><span style="font-size: x-small;">{</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">public</span><span style="color: #abb2bf;">:</span></span></div><div><span style="font-size: x-small;"> string id;</span></div><div><span style="font-size: x-small;"> string name;</span></div><div><span style="font-size: x-small;"> Node <span style="color: #e06c75;">*</span>next;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // id, name, next 為資料成員</span></span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">Node</span>(<span style="color: #61afef;">string</span> <span style="color: #d19a66; font-style: italic;">id</span><span style="color: #abb2bf;">,</span> <span style="color: #61afef;">string</span> <span style="color: #d19a66; font-style: italic;">name</span><span style="color: #abb2bf;">,</span> <span style="color: #61afef;">Node</span> <span style="color: #e06c75;">*</span><span style="color: #d19a66; font-style: italic;">next</span>)<span style="color: #abb2bf;">:</span></span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">id</span>(id)<span style="color: #abb2bf;">,</span> <span style="color: #98c379;">name</span>(name)<span style="color: #abb2bf;">,</span> <span style="color: #98c379;">next</span>(next) {};</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // Node(...)為建構式,利用「建構式成員初始化清單」將資料成員予以初始化</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // Constructors and member initializer lists</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://en.cppreference.com/w/cpp/language/constructor</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // --------------------------------------------------------- </span></span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">~Node</span>(); </span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">void</span> <span style="color: #98c379;">showInfo</span>();</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ~Node() 為 Destructor(解構式),當物件指標被 delete 掉時,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 此解構式自動被呼叫..</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // --------------------------------------------------------- </span></span></div><div><span style="font-size: x-small;">};</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;">//-------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;">// 以下透過「::」範圍解析運算子定義解構式 ~Node()及成員函數 showInfo()</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;">//-------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;">Node<span style="color: #abb2bf;">::</span><span style="color: #e06c75;">~</span><span style="color: #98c379;">Node</span>() {</span></div><div><span style="font-size: x-small;"> cout <span style="color: #e06c75;"><<</span> <span style="color: #e06c75;">this</span><span style="color: #abb2bf;">->name</span> <span style="color: #e06c75;"><<</span> <span style="color: #e5c07b;">"-動態配置被回收.."</span> <span style="color: #e06c75;"><<</span> endl;</span></div><div><span style="font-size: x-small;">} </span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;">//</span></span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">void</span> <span style="color: #61afef;">Node</span><span style="color: #abb2bf;">::</span><span style="color: #98c379;">showInfo</span>() {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"id:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">this</span><span style="color: #abb2bf;">-></span><span style="color: #abb2bf;">id</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"/"</span> </span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"name:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">this</span><span style="color: #abb2bf;">-></span><span style="color: #abb2bf;">name</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"/"</span></span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"本身節點位址:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">this</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"/"</span></span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"下一節點位址:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">this</span><span style="color: #abb2bf;">-></span><span style="color: #abb2bf;">next</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------</span></span></div><div><div style="line-height: 20px;"><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // this 是一個指標,而且隱含於類別成員函數之中. this 指向調用該成員函數之</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 物件自身,也就是該物件本身資料成員區塊在記憶體中的位址。若以類別衍生多個</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 物件言,不同物件各自擁有一份資料成員;然成員函數也就僅僅一份。至於同樣一</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 份成員函數又如何處理多份物件各自擁有的資料成員呢?答案就是「this」指標。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 緣此,當一個物件調用其成員函數時,編譯器會將目前該物件資料成員所在的記憶</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 體位址隱式地傳遞給成員函數中的 this 指標,當此,成員函數中的 this 指標</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 即指向該物件。簡言之,this 指標隱含於成員函數中,它用來指向調用它的物件。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 參考:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://openhome.cc/Gossip/CppGossip/thisPointer.html</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://www.bogotobogo.com/cplusplus/this_pointer.php</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://docs.microsoft.com/zh-tw/cpp/cpp/this-pointer?view=msvc-160</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // PS:資料成員 (data member)、成員函數 (member function)</span></span></div></div></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;">}</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;">//-------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> <span style="color: #98c379;">main</span>()</span></div><div><span style="font-size: x-small;">{</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">Node</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">root</span> <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">Node</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">current</span> <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">Node</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">move</span> <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span>; </span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // root, current, move 同為指向 Node 類別的指標變數,且初始化為 nullptr,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 進一步說,root, current, move 指標變數內容存放「所指向之Node 物件在記憶</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 體中的位址」,也就是說, root 本身內容是記憶體位址,而 *root 為該記憶體位</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 址所定址到的 Node 物件,這就是所謂的「依址取值」,也是一種間接定址法。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">string</span> <span style="color: #abb2bf;">getID</span><span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">getName</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"建立連結串列(id:2位數字,名字:自訂) 'exit' 離開..."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"請輸入id:"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">getline</span>(<span style="color: #61afef;">cin</span><span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">getID</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"節點名字:"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">getline</span>(<span style="color: #61afef;">cin</span><span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">getName</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">root</span> <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">new</span> <span style="color: #61afef;">Node</span>(<span style="color: #abb2bf;">getID</span><span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">getName</span><span style="color: #abb2bf;">,</span> <span style="color: #56b6c2;">nullptr</span>); </span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ----------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // root 是 Linked List 的起始節點,後續新生節點依序往後串接,串接動作則是透</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 過 Node 類別中的資料成員 next,而 next 宣告為「Node *next」代表為一個</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 指向 Node 類別的指標。換言之, next 指標變數存放「所指向之 Node 物件在記</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 憶體中的位址」。如此一來,各自已生成的 Node 節點之 next 指標便能維護(存放)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 其後續新生節點所在的記憶體位址,這種透過記憶體位址前後有序互相參照且彼此串聯</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 的結構,就是所謂的 Linked List(連結串列)。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">current</span> <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">root</span>;<span style="color: #676f7d;"> // 一開始,只有 root 被建立, 設定好起點,開始要往後串接了.</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">do</span></span></div><div><span style="font-size: x-small;"> {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"請輸入id:"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">getline</span>(<span style="color: #61afef;">cin</span><span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">getID</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"節點名字:"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">getline</span>(<span style="color: #61afef;">cin</span><span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">getName</span>);</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> //-------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">if</span> (<span style="color: #abb2bf;">getID</span> <span style="color: #98c379;">==</span> <span style="color: #e5c07b;">"exit"</span> <span style="color: #e06c75;">||</span> <span style="color: #abb2bf;">getName</span> <span style="color: #98c379;">==</span> <span style="color: #e5c07b;">"exit"</span>)</span></div><div><span style="font-size: x-small;"> {</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">break</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">move</span> <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">new</span> <span style="color: #61afef;">Node</span>(<span style="color: #abb2bf;">getID</span><span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">getName</span><span style="color: #abb2bf;">,</span> <span style="color: #56b6c2;">nullptr</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">current</span><span style="color: #abb2bf;">-></span><span style="color: #abb2bf;">next</span> <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">move</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">current</span> <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">move</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">current</span><span style="color: #abb2bf;">-></span><span style="color: #abb2bf;">next</span> <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">while</span> (<span style="color: #56b6c2;">true</span>);</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // --------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // <解析>:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // current:指向目前連結串列最後一個節點.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // move:動態產生新的節點.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // current->next = move:目前串列最後一個節點的 next 指標設定為新生節點,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 這個作用以記憶體層次來說就是:目前串列最後一個節點的 next 指標內容設定為</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 新生節點所在的記憶體位址。如此一來就能夠把 current 往後串上 move 了...</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 還記得嗎?「current:指向目前串列最後一個節點」,因此,為保持這樣的結構,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // => current = move => current 終於又指向了串列最後一個節點了..</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ※※※ 記得指標的意義:指標是用來存放變數或物件在記憶體中的位址。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 指標存放的是記憶體位址,而不是值(很重要!!!)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // current 所存內容是記憶體位址; *current 才是值(變數的值或一個物件實例)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 最後 current->next = nullptr => 避免懸空指標,更註記了連結串列的結尾.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // --------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"連結串列各節點(仔細觀察自身節點及下一節點位址變化):"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"--------------------------------------------"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">current</span> <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">root</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">move</span> <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">root</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> //</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">while</span> (<span style="color: #abb2bf;">current</span> <span style="color: #e06c75;">!=</span> <span style="color: #56b6c2;">nullptr</span>)</span></div><div><span style="font-size: x-small;"> {</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">current</span><span style="color: #abb2bf;">-></span><span style="color: #98c379;">showInfo</span>();</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">current</span> <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">current</span><span style="color: #abb2bf;">-></span><span style="color: #abb2bf;">next</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">delete</span> <span style="color: #abb2bf;">move</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">move</span> <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">current</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">root</span> <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ----------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 整個 LinkedList 所有的 Node 節點都是透過 new 動態記憶體配置而生。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 走訪過之節點若不再使用,記得將節點予以釋放並歸還給自由空間(用 delete)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 走訪過程:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 1. 設定由 root 起點開始 => current = root, current 負責依指標</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 之串接以完成循序走訪. 至於 move = root, 這 move 為善後之用.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 2. 判斷當前 current 是否為 nullptr, 若是 => 已到串列尾,結束.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 否則重複走訪,走訪期間輸出節點資訊.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 3. 利用 current = current->next 將走訪移至下一個節點,至於上一</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 個節點已輸出節點資訊,不再使用了 => delete move => 回收動態</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 記憶體配置。這 move 就跟著 current 隨侍在側(move = current),</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 其任務就是跟著善後做回收工作..</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ----------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 最後將 root 指標設定 nullptr => 避免 dangling pointer(懸空指標)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 所有串列節點已在走訪過程中一個又一個予以回收了(delete move)。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 因此無須再畫蛇添足作 delete current 或 delete root 了,否則再次</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // delete 已回收之動態記憶體配置 => 導致錯誤!!</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 這時只要設定 root = nullptr 即可,為何呢?因為整個走訪過程的關鍵處</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 在於: current = current->next => 如此重複到最後必然因條件判斷 </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // current = nullptr 成立而終止 while => 此時 current = nullptr,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 又加上 move = current,最終必令 current, move 同設定為 nullptr,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 設定為 nullptr => 不致釀成「懸空指標」問題.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ----------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // PS:若走訪結束「之後」又 delete move, delete current,如何呢? </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // => OK 的,在 C++ Primer 5th Edition 中道出:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 當 ptr = nullptr => delete ptr 總是沒有錯誤的!</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 反之,若上述沒有設定 root = nullptr => delete root => 錯誤!!!</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 理由:因為 root 所指向的動態配置早在先前 while 重複結構中予以回收了</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // (透過 delete move),當已釋放的記憶體又再度被 delete => 錯誤 !!</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 可參考:http://kailotus.blogspot.com/2020/11/c20pointer.html</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ----------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 設定 nullptr 是為避免「懸空指標」問題。但釋放及回收動態記憶體過程一定</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 要先 delete 指標變數,爾後再設定 nullptr,否則會導致記憶體洩漏問題.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 「懸空指標」及「憶體洩漏」則是使用原始指標的痛處!!!!!</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 以下做個實驗,驗證 current, move 是否為 nullptr</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> //</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">if</span> (<span style="color: #abb2bf;">current</span> <span style="color: #e06c75;">==</span> <span style="color: #56b6c2;">nullptr</span> <span style="color: #e06c75;">&&</span> <span style="color: #abb2bf;">move</span> <span style="color: #e06c75;">==</span> <span style="color: #56b6c2;">nullptr</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"current 及 move 已均為 nullptr"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"連結串列節點全部輸出 OK.."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">system</span>(<span style="color: #e5c07b;">"PAUSE"</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">return</span> <span style="color: #98c379;">EXIT_SUCCESS</span>;</span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="color: #61afef;"><span style="font-size: x-small;">執行結果:</span></span></div><div><span style="font-size: x-small;"><span style="color: #61afef;">建立連結串列</span>(id:<span style="color: #c678dd;">2</span>位數字,名字:自訂) <span style="color: #e5c07b;">'exit'</span> 離開...</span></div><div><span style="font-size: x-small;">請輸入id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">1</span></span></div><div><span style="font-size: x-small;">節點名字:C</span></div><div><span style="font-size: x-small;">請輸入id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">2</span></span></div><div><span style="font-size: x-small;">節點名字:Python</span></div><div><span style="font-size: x-small;">請輸入id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">3</span></span></div><div><span style="font-size: x-small;">節點名字:Java</span></div><div><span style="font-size: x-small;">請輸入id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">4</span></span></div><div><span style="font-size: x-small;">節點名字:C<span style="color: #e06c75;">++</span></span></div><div><span style="font-size: x-small;">請輸入id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">5</span></span></div><div><span style="font-size: x-small;">節點名字:C#</span></div><div><span style="font-size: x-small;">請輸入id:exit</span></div><div><span style="font-size: x-small;">節點名字:</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">連結串列各節點(仔細觀察自身節點及下一節點位址變化):</span></div><div><span style="color: #e06c75;"><span style="font-size: x-small;">--------------------------------------------</span></span></div><div><span style="font-size: x-small;">id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">1</span>/name:C/本身節點位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5f19c0</span>/下一節點位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5f1d30</span></span></div><div><span style="font-size: x-small;">C<span style="color: #e06c75;">-</span>動態配置被回收..</span></div><div><span style="font-size: x-small;">id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">2</span>/name:Python/本身節點位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5f1d30</span>/下一節點位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5f1d80</span></span></div><div><span style="font-size: x-small;">Python<span style="color: #e06c75;">-</span>動態配置被回收..</span></div><div><span style="font-size: x-small;">id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">3</span>/name:Java/本身節點位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5f1d80</span>/下一節點位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5f1dd0</span></span></div><div><span style="font-size: x-small;">Java<span style="color: #e06c75;">-</span>動態配置被回收..</span></div><div><span style="font-size: x-small;">id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">4</span>/name:C<span style="color: #e06c75;">++</span>/本身節點位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5f1dd0</span>/下一節點位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5f1e20</span></span></div><div><span style="font-size: x-small;">C<span style="color: #e06c75;">++-</span>動態配置被回收..</span></div><div><span style="font-size: x-small;">id:<span style="color: #e06c75;">0</span><span style="color: #c678dd;">5</span>/name:C#/本身節點位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5f1e20</span>/下一節點位址:<span style="color: #c678dd;">0</span></span></div><div><span style="font-size: x-small;">C#<span style="color: #e06c75;">-</span>動態配置被回收..</span></div><div><span style="font-size: x-small;">current 及 move 已均為 <span style="color: #56b6c2;">nullptr</span></span></div><div><span style="font-size: x-small;">連結串列節點全部輸出 OK..</span></div><div><span style="font-size: x-small;">請按任意鍵繼續 . . .</span></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-1953380807811857262020-11-12T09:51:00.005+08:002020-11-12T09:51:56.457+08:00閒談C++(20):Pointer 指標,再談談原始指標<a href="https://docs.microsoft.com/zh-tw/cpp/cpp/welcome-back-to-cpp-modern-cpp?view=msvc-160" target="_blank">Modern C++</a>(C++11及其以後的版本),特別強調應該使用<span style="color: #cc0000; font-size: medium;">智慧型指標(Smart Pointer)</span>以取代原始指標,這個原始指標就是本文範例所示。然為何該使用 Smart Pointer 呢?因為原始指標操作若涉及動態記憶體配置則易產生記憶體相關問題,如 Memory Leak(記憶體洩漏) 或 Dangling Pointer(懸空指標)。使用 Smart Pointer 之前,對此原始指標稍加探究,為文以記之...<div><br /></div><div><div style="background-color: #282c34; color: #bbbbbb; font-family: "Source Code Pro", Consolas, "Courier New", monospace; line-height: 20px; white-space: pre;"><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><iostream></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">using</span> <span style="color: #56b6c2;">namespace</span> std;</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> <span style="color: #98c379;">main</span>() {</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">a</span> <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">20</span>;<span style="color: #676f7d;"> // 靜態記憶體配置</span></span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">b</span> <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">30</span>;<span style="color: #676f7d;"> // 靜態記憶體配置</span></span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">ptr</span> <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">new</span> <span style="color: #56b6c2;">int</span>(<span style="color: #c678dd;">10</span>);<span style="color: #676f7d;"> // 動態記憶體配置, 有 new, 之後記得要 delete</span></span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">dng</span> <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span>;<span style="color: #676f7d;"> // dng 初始化為 nullptr,不綁定到任何對象</span></span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">dng</span> <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">ptr</span>;<span style="color: #676f7d;"> // dng 同 ptr 指向 new int(10) 動態配置空間</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"------------------------------------------------------"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>; </span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"a = "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">a</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"b = "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">b</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"int *ptr = new int(10)"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"ptr內容(位址):"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">ptr</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">",指向之值:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">ptr</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"dng內容(位址):"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">dng</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">",指向之值:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">dng</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // --------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 這裡的 ptr內容(位址) 及 dng內容(位址) 係指指標變數 ptr, dng 所存內容,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 而不是指標變數所在的記憶體位址</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // --------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"------------------------------------------------------"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">delete</span> <span style="color: #abb2bf;">ptr</span>;<span style="color: #676f7d;"> // 透過 delete ptr 把 new int(10) 空間釋放並歸還給自由空間</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // delete dng; // 錯誤,因為 dng 所指向的動態記憶體已被釋放,不可重複為之</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"執行 delete ptr,但還沒有設定 ptr = nullptr,結果如下.."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"ptr內容(位址):"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">ptr</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">",指向之值:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">ptr</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"dng內容(位址):"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">dng</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">",指向之值:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">dng</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"此時,ptr、dng 內容與 delete ptr 之前相同,但指向之值已被釋放,內容不可預測.."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"問題是經過 delete ptr 後,ptr 所指向的動態記憶體空間已被回收.."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"這時的 ptr、dng 同指向已回收的記憶空間 => 懸空指標(dangling pointer).."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"該如何呢?!"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"=> ptr = nullptr 且 dng = nullptr"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">ptr</span> <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">dng</span> <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"執行指定 nullptr 後,ptr, dng 不再綁定任何對象.. "</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"ptr內容(位址):"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">ptr</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;<span style="color: #676f7d;"> // cout << *ptr => 錯誤!! 因為 ptr = nullptr</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"dng內容(位址):"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">dng</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;<span style="color: #676f7d;"> // cout << *dng => 錯誤!! 因為 dng = nullptr</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"要先 delete 指標變數以釋放回收動態配置,再做指定 nullptr,否則會產生 memory leak.."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"什麼是 merory leak(記憶體洩漏)?"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"簡言之「new 出來的動態記憶體配置,最後沒做 delete 以釋放不再使用的"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"記憶體配置並歸還給自由空間 => memory leak.."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"上例若倒過來先 ptr = nullptr 而後 delete ptr => memory leak.."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"因為當 ptr 指向的動態配置還在時,若先 ptr = nullptr => 截斷了 ptr 與動態配置依址取值關係。"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"換言之,當還沒有 delete ptr 以釋放回收動態配置之前就直接 ptr = nullptr ,那麼"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"這動態配置就會成為「無主孤魂」了.."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">ptr</span> <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">a</span>;<span style="color: #676f7d;"> // re-assign the ptr to &a</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"ptr內容(位址):"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">ptr</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">",指向之值:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">ptr</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // delete ptr; // 錯誤,因為 ptr = &a 只是指向一般變數,非動態配置,故不能用 delete</span></span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">ptr</span> <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">b</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"ptr內容(位址):"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">ptr</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">",指向之值:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">ptr</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">ptr</span> <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">40</span>;<span style="color: #676f7d;"> // ptr 指標指向之值更改為 40 => 更新 b 變數為 40</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"ptr內容(位址):"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">ptr</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">",指向之值:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">ptr</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">ptr</span> <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span>;<span style="color: #676f7d;"> // 設定 ptr 不再綁定到任何對象</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"ptr = nullptr 後,ptr內容(位址):"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">ptr</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"經過 ptr = &b 及 *ptr = 40 以後 => b = "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">b</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"結尾語:delete ptr 時機:當 ptr 指向一個動態配置對象方可為之.."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="color: #61afef;"><span style="font-size: x-small;">執行結果:</span></span></div><span style="font-size: x-small;"><br /></span><div><span style="color: #e06c75;"><span style="font-size: x-small;">------------------------------------------------------</span></span></div><div><span style="font-size: x-small;">a <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">20</span></span></div><div><span style="font-size: x-small;">b <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">30</span></span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> <span style="color: #e06c75;">*</span>ptr <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">new</span> <span style="color: #56b6c2;">int</span>(<span style="color: #c678dd;">10</span>)</span></div><div><span style="font-size: x-small;">ptr內容(位址):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531be0</span>,指向之值:<span style="color: #c678dd;">10</span></span></div><div><span style="font-size: x-small;">dng內容(位址):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531be0</span>,指向之值:<span style="color: #c678dd;">10</span></span></div><div><span style="color: #e06c75;"><span style="font-size: x-small;">------------------------------------------------------</span></span></div><div><span style="font-size: x-small;">執行 <span style="color: #e06c75;">delete</span> ptr,但還沒有設定 ptr <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span>,結果如下..</span></div><div><span style="font-size: x-small;">ptr內容(位址):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531be0</span>,指向之值:<span style="color: #c678dd;">5445744</span></span></div><div><span style="font-size: x-small;">dng內容(位址):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">531be0</span>,指向之值:<span style="color: #c678dd;">5445744</span></span></div><div><span style="font-size: x-small;">此時,ptr、dng 內容與 <span style="color: #e06c75;">delete</span> ptr 之前相同,但指向之值已被釋放,內容不可預測..</span></div><div><span style="font-size: x-small;">問題是經過 <span style="color: #e06c75;">delete</span> ptr 後,ptr 所指向的動態記憶體空間已被回收..</span></div><div><span style="font-size: x-small;">這時的 ptr、dng 同指向已回收的記憶空間 <span style="color: #e06c75;">=></span> 懸空指標(dangling pointer)..</span></div><div><span style="font-size: x-small;">該如何呢?<span style="color: #e06c75;">!</span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">=></span> ptr <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span> 且 dng <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span></span></div><div><span style="font-size: x-small;">執行指定 <span style="color: #56b6c2;">nullptr</span> 後,ptr<span style="color: #abb2bf;">,</span> dng 不再綁定任何對象..</span></div><div><span style="font-size: x-small;">ptr內容(位址):<span style="color: #c678dd;">0</span></span></div><div><span style="font-size: x-small;">dng內容(位址):<span style="color: #c678dd;">0</span></span></div><div><span style="font-size: x-small;">要先 <span style="color: #e06c75;">delete</span> 指標變數以釋放回收動態配置,再做指定 <span style="color: #56b6c2;">nullptr</span>,否則會產生 memory leak..</span></div><div><span style="font-size: x-small;">什麼是 merory <span style="color: #98c379;">leak</span>(記憶體洩漏)?</span></div><div><span style="font-size: x-small;">簡言之「<span style="color: #e06c75;">new</span> 出來的動態記憶體配置,最後沒做 <span style="color: #e06c75;">delete</span> 以釋放不再使用的</span></div><div><span style="font-size: x-small;">記憶體配置並歸還給自由空間 <span style="color: #e06c75;">=></span> memory leak..</span></div><div><span style="font-size: x-small;">上例若倒過來先 ptr <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span> 而後 <span style="color: #e06c75;">delete</span> ptr <span style="color: #e06c75;">=></span> memory leak..</span></div><div><span style="font-size: x-small;">因為當 ptr 指向的動態配置還在時,若先 ptr <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span> <span style="color: #e06c75;">=></span> 截斷了 ptr 與動態配置依址取值關係。</span></div><div><span style="font-size: x-small;">換言之,當還沒有 <span style="color: #e06c75;">delete</span> ptr 以釋放回收動態配置之前就直接 ptr <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span> ,那麼</span></div><div><span style="font-size: x-small;">這動態配置就會成為「無主孤魂」了..</span></div><div><span style="font-size: x-small;">ptr內容(位址):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fe3c</span>,指向之值:<span style="color: #c678dd;">20</span></span></div><div><span style="font-size: x-small;">ptr內容(位址):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fe38</span>,指向之值:<span style="color: #c678dd;">30</span></span></div><div><span style="font-size: x-small;">ptr內容(位址):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fe38</span>,指向之值:<span style="color: #c678dd;">40</span></span></div><div><span style="font-size: x-small;">ptr <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">nullptr</span> 後,ptr內容(位址):<span style="color: #c678dd;">0</span></span></div><div><span style="font-size: x-small;">經過 ptr <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">&</span>b 及 <span style="color: #e06c75;">*</span>ptr <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">40</span> 以後 <span style="color: #e06c75;">=></span> b <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">40</span></span></div><div><span style="font-size: x-small;">結尾語:<span style="color: #e06c75;">delete</span> ptr 時機:當 ptr 指向一個動態配置對象方可為之..</span></div></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-24000111796038397752020-11-07T14:59:00.008+08:002020-11-07T16:05:39.325+08:00閒談C++(19):&取址、* 指標與陣列之記憶體位址解析<div><span style="font-size: medium;"><span style="color: #990000;">指標(Pointer)是一種變數,用來存放變數在記憶體中的位址</span>。</span></div><div><span style="font-family: Source Code Pro; font-size: medium;">int num = 100;</span></div><div><span style="font-family: Source Code Pro; font-size: medium;">int *ptr;</span></div><div><span style="font-family: Source Code Pro; font-size: medium;">ptr = &num;</span></div><div><span style="font-size: medium;">=> <span style="color: #2b00fe;"><span style="font-family: Source Code Pro;">ptr </span>的內容是一個位址</span>(記憶體位址),本例為<span style="font-family: Source Code Pro;"> <span style="color: #800180;">num</span></span><span style="color: #800180;"> 變數在記憶體中的位址</span>;而 <span style="color: #cc0000; font-family: Source Code Pro;">*ptr </span>則是調用<span style="color: #800180;">該位址所存放的資料(依址取值)</span>,也就是 100。透過指標取值(<span style="font-family: Source Code Pro;">*ptr)</span>就是<span style="color: #2b00fe;">間接定址</span>。<br /><br /></span></div><div><span style="font-size: large;"><span style="color: #cc0000;">指標</span>就是用來<span style="color: #2b00fe;">存放</span><span style="color: #800180;">變數或物件</span><span style="color: #38761d;">在記憶體中之位址</span>,也就是說指標的內容是「記憶體位址」。</span></div><div><br /></div><div><div style="background-color: #282c34; color: #bbbbbb; font-family: "Source Code Pro", Consolas, "Courier New", monospace; line-height: 20px; white-space: pre;"><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><iostream></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><array></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">using</span> <span style="color: #56b6c2;">namespace</span> std;</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> <span style="color: #98c379;">main</span>() {</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">intPtr</span> <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">new</span> <span style="color: #56b6c2;">int</span>(<span style="color: #c678dd;">20</span>);<span style="color: #676f7d;"> // Direct initialization</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"intPtr 記憶體位址:"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">intPtr</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" , *intPtr:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">intPtr</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">intPtr</span> <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">30</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"intPtr 記憶體位址:"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">intPtr</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" , *intPtr:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">intPtr</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">delete</span> <span style="color: #abb2bf;">intPtr</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">string</span> <span style="color: #abb2bf;">ss</span> <span style="color: #e06c75;">=</span> <span style="color: #e5c07b;">"Hello World"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">string</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">strPtr</span> <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">ss</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"strPtr 記憶體位址:"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">strPtr</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" , *strPtr:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">strPtr</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 透過 new:動態分配記憶體空間;delete:回收記憶體。若沒有</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 回收掉因 new 而後不再使用之記憶體空間 => Memory leak</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">noList</span>[<span style="color: #c678dd;">5</span>] <span style="color: #e06c75;">=</span> {<span style="color: #c678dd;">13</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">57</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">24</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">68</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">99</span>};</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">noPtr</span> <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">noList</span>; </span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 相當於取 noList 所在記憶體位址並指定給指標變數 noPtr 時,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 因為 noList 為陣列結構,故單就輸出 noList 所在記憶體位址,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 可用 cout << noList , 亦可 cout << &noList </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 但 int *noPtr = noList 卻不可 int *noPtr = &noList ,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 不過卻可表達成:int *noPtr = &noList[0];</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ※※※ 很重要 ※※※</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // noList為陣列變數:若 cout << noList 則表示輸出 noList </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 所在記憶體起始位址。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // noList為陣列變數:若 cout << &noList 亦表示輸出 noList </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 所在記憶體起始位址。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // noPtr 為指標變數:若 cout << noPtr 則表示輸出 noPtr 指</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 標變數所存內容值(記憶體位址)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // noPtr 為指標變數:若 cout << &noPtr 則表示輸出 noPtr 指</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 標變數所在記憶體位址。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"noList 陣列所在記憶體位址(noList):"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">noList</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"noList 陣列所在記憶體位址(&noList):"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">noList</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"noList 陣列所在記憶體位址(&noList[0]):"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">noList</span>[<span style="color: #c678dd;">0</span>] <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"noPtr 指標變數所在記憶體位址(&noPtr):"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">noPtr</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"noPtr 指標變數所存內容(noPtr):"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">noPtr</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 以陣列 noList 來說,cout << noList 與 cout << &noList</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 及 cout << &noList[0] 同指輸出 nolist 所在記憶體的位址。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 又 int *noPtr = &noList[0] 敘述後, noPtr, &noPtr</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 是不相同的涵義。noPtr => 本身為指向整數型的指標,故其內容值</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 為記憶體位址。又 &noPtr => 表示 noPtr 這指標變數所在記憶體</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 位址.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">len</span> <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">0</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">tmp</span> <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">0</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">idx</span> <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">0</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"請輸入陣列長度:"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cin</span> <span style="color: #98c379;">>></span> <span style="color: #abb2bf;">len</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #e06c75;">*</span><span style="color: #abb2bf;">boxPtr</span> <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">new</span> <span style="color: #56b6c2;">int</span>[<span style="color: #abb2bf;">len</span>];</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"請輸入 "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">len</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" 個數值(空白隔開):"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">while</span> (<span style="color: #61afef;">cin</span> <span style="color: #98c379;">>></span> <span style="color: #abb2bf;">tmp</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">*</span>(<span style="color: #abb2bf;">boxPtr</span><span style="color: #e06c75;">+</span><span style="color: #abb2bf;">idx</span>) <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">tmp</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">idx</span><span style="color: #e06c75;">++</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">if</span> (<span style="color: #abb2bf;">idx</span> <span style="color: #e06c75;">>=</span> <span style="color: #abb2bf;">len</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">break</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 因為陣列具有指標的性質,反之,指標可視為一種陣列的操作。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 故 *(boxPtr+idx) => 相當於 boxPtr[idx] 陣列取值.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 指標變數 boxPtr 可以被視為一陣列名稱。但若以記憶體位址的視</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 角切入,陣列與指標在記憶體位址的變化與對應關係則需鑑別清楚。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 解析:(& 為取址符號)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // A 是一個陣列變數: => A 及 &A 及 &A[0] 同指 A 陣列的起</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 始位址(A 陣列在記憶體的起始位址)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // A 是一個指標變數: => A 指的是指標變數所存資料內容(記憶體</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 位址,用來間接定址);而 &A 代表指標變數 A 所在記憶體位址</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // --------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 此例為:int *boxPtr = new int[len]</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 對於 boxPtr 指標變數內容的意涵應該是「一個記憶體位址」,而</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 這個記憶體位址非指 boxPtr 指標變數所在記憶體位址,而是代表</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // boxPtr 所指向之動態陣列之起始位址(間接定址),其值就相當於</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // &boxPtr[0],但不可用 &boxPtr 表示, 因為 boxPtr 實質為</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 指標而非陣列。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"整數型別大小:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">sizeof</span>(<span style="color: #56b6c2;">int</span>) <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" bytes"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"----------------------------------------------------"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">">>> 關於 int *boxPtr = new int[len] 相關論述 <<<"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"boxPtr 為一個指向動態記憶體配置的指標變數,雖為指標,"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"但操作上也可視為陣列來處理。不過就記憶體層面之理解,當"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"成指標看待會較為清晰明確.."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"----------------------------------------------------"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"boxPtr 指標變數所在記憶體位址(&boxPtr) => "</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">boxPtr</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"boxPtr 指標變數所存資料內容(boxPtr) => "</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">boxPtr</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"&boxPtr[0]:也就是 boxPtr[0]元素所在位址 => "</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">boxPtr</span>[<span style="color: #c678dd;">0</span>] <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"仔細觀察下列記憶體位址變化.."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> (<span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">i</span><span style="color: #e06c75;">=</span><span style="color: #c678dd;">0</span>; <span style="color: #abb2bf;">i</span><span style="color: #e06c75;"><</span><span style="color: #abb2bf;">len</span>; <span style="color: #abb2bf;">i</span><span style="color: #e06c75;">++</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"&boxPtr["</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">i</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"]:"</span> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">&</span><span style="color: #abb2bf;">boxPtr</span>[<span style="color: #abb2bf;">i</span>] <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">","</span> </span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"(boxPtr+"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">i</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">");"</span> <span style="color: #98c379;"><<</span> (<span style="color: #abb2bf;">boxPtr</span><span style="color: #e06c75;">+</span><span style="color: #abb2bf;">i</span>) <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" => "</span> </span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;"><<</span> <span style="color: #e06c75;">*</span>(<span style="color: #abb2bf;">boxPtr</span><span style="color: #e06c75;">+</span><span style="color: #abb2bf;">i</span>) <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 這裡的 *(boxPtr+i) , 雖然每次 i 值作遞增 1 的變化,然由於</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // boxPtr+i 為記憶體位址作用層次,實則每次增量為 int 型別 4</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // (bytes) 之大小。也就是說 *(boxPtr+3) 等同於 boxPtr[3] </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">delete[]</span> <span style="color: #abb2bf;">boxPtr</span>;<span style="color: #676f7d;"> // 回收連續空間 => delete[]</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // </span></span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="color: #61afef;"><span style="font-size: x-small;">執行結果:</span></span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"><span style="color: #61afef;">intPtr</span> 記憶體位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5119b0</span> <span style="color: #abb2bf;">,</span> <span style="color: #e06c75;">*</span>intPtr:<span style="color: #c678dd;">20</span></span></div><div><span style="font-size: x-small;">intPtr 記憶體位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5119b0</span> <span style="color: #abb2bf;">,</span> <span style="color: #e06c75;">*</span>intPtr:<span style="color: #c678dd;">30</span></span></div><div><span style="font-size: x-small;">strPtr 記憶體位址:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fe00</span> <span style="color: #abb2bf;">,</span> <span style="color: #e06c75;">*</span>strPtr:Hello World</span></div><div><span style="font-size: x-small;">noList 陣列所在記憶體位址(noList):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fde0</span></span></div><div><span style="font-size: x-small;">noList 陣列所在記憶體位址(<span style="color: #e06c75;">&</span>noList):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fde0</span></span></div><div><span style="font-size: x-small;">noList 陣列所在記憶體位址(<span style="color: #e06c75;">&</span><span style="color: #61afef;">noList</span>[<span style="color: #c678dd;">0</span>]):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fde0</span></span></div><div><span style="font-size: x-small;">noPtr 指標變數所在記憶體位址(<span style="color: #e06c75;">&</span>noPtr):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fdd8</span></span></div><div><span style="font-size: x-small;">noPtr 指標變數所存內容(noPtr):<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fde0</span></span></div><div><span style="font-size: x-small;">請輸入陣列長度:<span style="color: #c678dd;">5</span></span></div><div><span style="font-size: x-small;">請輸入 <span style="color: #c678dd;">5</span> 個數值(空白隔開):<span style="color: #c678dd;">43</span> <span style="color: #c678dd;">21</span> <span style="color: #c678dd;">75</span> <span style="color: #c678dd;">35</span> <span style="color: #c678dd;">67</span> <span style="color: #c678dd;">94</span> <span style="color: #c678dd;">52</span> <span style="color: #c678dd;">79</span></span></div><div><span style="font-size: x-small;">整數型別大小:<span style="color: #c678dd;">4</span> bytes</span></div><div><span style="color: #e06c75;"><span style="font-size: x-small;">----------------------------------------------------</span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">>>></span> 關於 <span style="color: #56b6c2;">int</span> <span style="color: #e06c75;">*</span>boxPtr <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">new</span> <span style="color: #56b6c2;">int</span>[len] 相關論述 <span style="color: #e06c75;"><<<</span></span></div><div><span style="font-size: x-small;">boxPtr 為一個指向動態記憶體配置的指標變數,雖為指標,</span></div><div><span style="font-size: x-small;">但操作上也可視為陣列來處理。不過就記憶體層面之理解,當</span></div><div><span style="font-size: x-small;">成指標看待會較為清晰明確..</span></div><div><span style="color: #e06c75;"><span style="font-size: x-small;">----------------------------------------------------</span></span></div><div><span style="font-size: x-small;">boxPtr 指標變數所在記憶體位址(<span style="color: #e06c75;">&</span>boxPtr) <span style="color: #e06c75;">=></span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">23fdc8</span></span></div><div><span style="font-size: x-small;">boxPtr 指標變數所存資料內容(boxPtr) <span style="color: #e06c75;">=></span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5119b0</span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">&</span><span style="color: #61afef;">boxPtr</span>[<span style="color: #c678dd;">0</span>]:也就是 <span style="color: #61afef;">boxPtr</span>[<span style="color: #c678dd;">0</span>]元素所在位址 <span style="color: #e06c75;">=></span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5119b0</span></span></div><div><span style="font-size: x-small;">仔細觀察下列記憶體位址變化..</span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">&</span><span style="color: #61afef;">boxPtr</span>[<span style="color: #c678dd;">0</span>]:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5119b0</span>,(boxPtr<span style="color: #e06c75;">+</span><span style="color: #c678dd;">0</span>);<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5119b0</span> <span style="color: #e06c75;">=></span> <span style="color: #c678dd;">43</span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">&</span><span style="color: #61afef;">boxPtr</span>[<span style="color: #c678dd;">1</span>]:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5119b4</span>,(boxPtr<span style="color: #e06c75;">+</span><span style="color: #c678dd;">1</span>);<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5119b4</span> <span style="color: #e06c75;">=></span> <span style="color: #c678dd;">21</span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">&</span><span style="color: #61afef;">boxPtr</span>[<span style="color: #c678dd;">2</span>]:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5119b8</span>,(boxPtr<span style="color: #e06c75;">+</span><span style="color: #c678dd;">2</span>);<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5119b8</span> <span style="color: #e06c75;">=></span> <span style="color: #c678dd;">75</span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">&</span><span style="color: #61afef;">boxPtr</span>[<span style="color: #c678dd;">3</span>]:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5119bc</span>,(boxPtr<span style="color: #e06c75;">+</span><span style="color: #c678dd;">3</span>);<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5119bc</span> <span style="color: #e06c75;">=></span> <span style="color: #c678dd;">35</span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">&</span><span style="color: #61afef;">boxPtr</span>[<span style="color: #c678dd;">4</span>]:<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5119c0</span>,(boxPtr<span style="color: #e06c75;">+</span><span style="color: #c678dd;">4</span>);<span style="color: #e06c75;">0x</span><span style="color: #c678dd;">5119c0</span> <span style="color: #e06c75;">=></span> <span style="color: #c678dd;">67</span></span></div></div></div><div><br /></div><div><span style="color: #990000; font-size: medium;">以圖解析</span>:<br /><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-aHvdU9fC9Lc/X6ZFr6Aoq0I/AAAAAAAAUqc/5J4hdGU2Jy8JCydjPm9ni49THgTsVJaWACLcBGAsYHQ/s694/pointer.jpg" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="614" data-original-width="694" src="https://1.bp.blogspot.com/-aHvdU9fC9Lc/X6ZFr6Aoq0I/AAAAAAAAUqc/5J4hdGU2Jy8JCydjPm9ni49THgTsVJaWACLcBGAsYHQ/s16000/pointer.jpg" /></a></div><br /><div><br /></div><div><br /></div><div><br /></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-12641322595580787212020-11-04T13:50:00.007+08:002020-11-04T13:50:58.588+08:00閒談C++(18):C++ STL 容器 vector<div style="background-color: #282c34; color: #bbbbbb; font-family: "Source Code Pro", Consolas, "Courier New", monospace; line-height: 20px; white-space: pre;"><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><iostream></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><vector></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><algorithm></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">using</span> <span style="color: #56b6c2;">namespace</span> std;</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> <span style="color: #98c379;">main</span>() {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">vector</span><span style="color: #e06c75;"><</span><span style="color: #56b6c2;">int</span><span style="color: #e06c75;">></span> <span style="color: #abb2bf;">box</span> <span style="color: #e06c75;">=</span> {<span style="color: #c678dd;">21</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">53</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">42</span>}; </span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">getValue</span> <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">0</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -----------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // box 初始化為 3 個元素且型別為 int 的 vector, vector 為可變</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 動長度的線性容器,後續可以透過 push_back 添加元素</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"請輸入若干數值(數值之間空白隔開,非數值代表結束輸入):"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">while</span> (<span style="color: #61afef;">cin</span> <span style="color: #98c379;">>></span> <span style="color: #abb2bf;">getValue</span><span style="color: #abb2bf;">,</span> <span style="color: #e06c75;">!</span><span style="color: #61afef;">cin</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">eof</span>()) {</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">if</span> (<span style="color: #e06c75;">!</span><span style="color: #61afef;">cin</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">fail</span>()) {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">getValue</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" "</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">push_back</span>(<span style="color: #abb2bf;">getValue</span>);<span style="color: #676f7d;"> // 新增元素</span></span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">else</span> {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"輸入結束.."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">break</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // while (cin >> getValue, !cin.eof()) </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 說明一下: cin.eof(), 在 Windows 系統,當按下 Ctrl+Z(^Z)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 時,=> cin 讀到 Ctrl+Z => 結束 while 迴圈。故在沒有按下</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // Ctrl+Z 的前提下,cin 不斷的取值,但若 cin 取到的值不為數值</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 型別時 => 引發 cin.fail(),故判斷 cin.fail()之真假來決定</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 是否繼續 cin 動作.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 整個 while 的表達式為:cin >> getValue 要先做,至於是否</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 進入整個 while 迴圈則由最後一個式子 !cin.eof() 來決定..</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 對於 cin >> getValue 而言, 如果輸入了非整數型態資料 =></span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 導致 cin.fail() 成立;故要結束輸入作業,可以給予一個非數值</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 的輸入即可.. </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ---------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cin</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">clear</span>();</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cin</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">ignore</span>(<span style="color: #61afef;">numeric_limits</span><std<span style="color: #abb2bf;">::</span><span style="color: #61afef;">streamsize</span>><span style="color: #abb2bf;">::</span><span style="color: #98c379;">max</span>()<span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">'</span><span style="color: #56b6c2;">\n</span><span style="color: #e5c07b;">'</span>);</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // cin.clear():clears the error flag on cin (so that </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // future I/O operations will work correctly)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // cin.ignore(...):把按下 Enter('\n') 鍵之前所有存放在輸入緩</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 衝區的內容清除掉,結合 cin.clear() 為避免上一階段 cin fail</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 掉(當 cin >> getValue 輸入非數值資料時 => cin.fail())以後</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 所導致的 cin 無效.. </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"box 的第一個元素:"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">front</span>() <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"box 的最後一個元素:"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">back</span>() <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"box 的元素個數:"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">size</span>() <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"利用 iterator 進行迭代走訪所有元素:"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">vector</span><<span style="color: #56b6c2;">int</span>><span style="color: #abb2bf;">::</span><span style="color: #61afef;">iterator</span> <span style="color: #abb2bf;">itr</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> (<span style="color: #abb2bf;">itr</span><span style="color: #98c379;">=</span><span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">begin</span>(); <span style="color: #abb2bf;">itr</span><span style="color: #98c379;">!=</span><span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">end</span>(); <span style="color: #abb2bf;">itr</span><span style="color: #98c379;">++</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">*</span><span style="color: #abb2bf;">itr</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" "</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">insert</span>(<span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">begin</span>()<span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">5</span>); </span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">insert</span>(<span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">begin</span>()<span style="color: #98c379;">+</span><span style="color: #c678dd;">3</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">17</span>); </span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // box.insert(box.begin(), 5), box 開頭位置插入5 => box[0]=5</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // box.insert(box.begin()+i, n) => box 開頭位置位移 i 的位置</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 插入 n => box[i] = n </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // </span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"box 執行 insert 作業後的結果:"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> (<span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">i</span><span style="color: #e06c75;">=</span><span style="color: #c678dd;">0</span>; <span style="color: #abb2bf;">i</span><span style="color: #e06c75;"><</span><span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">size</span>(); <span style="color: #abb2bf;">i</span><span style="color: #e06c75;">++</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">at</span>(<span style="color: #abb2bf;">i</span>) <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" "</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -----------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">sort</span>(<span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">begin</span>()<span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">end</span>());<span style="color: #676f7d;"> // 預設排序:小->大</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"box 排序結果(小->大):"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> (<span style="color: #56b6c2;">auto</span> <span style="color: #abb2bf;">item</span> <span style="color: #abb2bf;">:</span> <span style="color: #abb2bf;">box</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">item</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" "</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -----------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">pop_back</span>();</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"box.pop_back()刪除元素後:"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> (<span style="color: #56b6c2;">auto</span> <span style="color: #abb2bf;">item</span> <span style="color: #abb2bf;">:</span> <span style="color: #abb2bf;">box</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">item</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" "</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">執行結果:</span></div><div><span style="font-size: x-small;"><span style="color: #61afef;">請輸入若干數值</span>(數值之間空白隔開,非數值代表結束輸入):<span style="color: #c678dd;">39</span> <span style="color: #c678dd;">81</span> <span style="color: #c678dd;">56</span> <span style="color: #c678dd;">47</span> <span style="color: #c678dd;">3</span> <span style="color: #c678dd;">75</span> <span style="color: #c678dd;">11</span> <span style="color: #c678dd;">63</span> .</span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">39</span> <span style="color: #c678dd;">81</span> <span style="color: #c678dd;">56</span> <span style="color: #c678dd;">47</span> <span style="color: #c678dd;">3</span> <span style="color: #c678dd;">75</span> <span style="color: #c678dd;">11</span> <span style="color: #c678dd;">63</span></span></div><div><span style="font-size: x-small;">輸入結束..</span></div><div><span style="font-size: x-small;">box 的第一個元素:<span style="color: #c678dd;">21</span></span></div><div><span style="font-size: x-small;">box 的最後一個元素:<span style="color: #c678dd;">63</span></span></div><div><span style="font-size: x-small;">box 的元素個數:<span style="color: #c678dd;">11</span></span></div><div><span style="font-size: x-small;">利用 iterator 進行迭代走訪所有元素:<span style="color: #c678dd;">21</span> <span style="color: #c678dd;">53</span> <span style="color: #c678dd;">42</span> <span style="color: #c678dd;">39</span> <span style="color: #c678dd;">81</span> <span style="color: #c678dd;">56</span> <span style="color: #c678dd;">47</span> <span style="color: #c678dd;">3</span> <span style="color: #c678dd;">75</span> <span style="color: #c678dd;">11</span> <span style="color: #c678dd;">63</span></span></div><div><span style="font-size: x-small;">box 執行 insert 作業後的結果:<span style="color: #c678dd;">5</span> <span style="color: #c678dd;">21</span> <span style="color: #c678dd;">53</span> <span style="color: #c678dd;">17</span> <span style="color: #c678dd;">42</span> <span style="color: #c678dd;">39</span> <span style="color: #c678dd;">81</span> <span style="color: #c678dd;">56</span> <span style="color: #c678dd;">47</span> <span style="color: #c678dd;">3</span> <span style="color: #c678dd;">75</span> <span style="color: #c678dd;">11</span> <span style="color: #c678dd;">63</span></span></div><div><span style="font-size: x-small;">box 排序結果(小<span style="color: #e06c75;">-></span>大):<span style="color: #c678dd;">3</span> <span style="color: #c678dd;">5</span> <span style="color: #c678dd;">11</span> <span style="color: #c678dd;">17</span> <span style="color: #c678dd;">21</span> <span style="color: #c678dd;">39</span> <span style="color: #c678dd;">42</span> <span style="color: #c678dd;">47</span> <span style="color: #c678dd;">53</span> <span style="color: #c678dd;">56</span> <span style="color: #c678dd;">63</span> <span style="color: #c678dd;">75</span> <span style="color: #c678dd;">81</span></span></div><div><span style="font-size: x-small;"><span style="color: #61afef;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">pop_back</span>()刪除元素後:<span style="color: #c678dd;">3</span> <span style="color: #c678dd;">5</span> <span style="color: #c678dd;">11</span> <span style="color: #c678dd;">17</span> <span style="color: #c678dd;">21</span> <span style="color: #c678dd;">39</span> <span style="color: #c678dd;">42</span> <span style="color: #c678dd;">47</span> <span style="color: #c678dd;">53</span> <span style="color: #c678dd;">56</span> <span style="color: #c678dd;">63</span> <span style="color: #c678dd;">75</span></span></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-12125878980143195012020-11-03T13:43:00.007+08:002020-11-03T14:23:20.422+08:00閒談C++(17):C++ STL 容器 array<div style="background-color: #282c34; color: #bbbbbb; font-family: "Source Code Pro", Consolas, "Courier New", monospace; line-height: 20px; white-space: pre;"><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><iostream></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><array></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><algorithm></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">using</span> <span style="color: #56b6c2;">namespace</span> std;</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> <span style="color: #98c379;">main</span>() {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">array</span><span style="color: #e06c75;"><</span><span style="color: #56b6c2;">int</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">10</span><span style="color: #e06c75;">></span> <span style="color: #abb2bf;">box</span> <span style="color: #e06c75;">=</span> {<span style="color: #c678dd;">0</span>}; </span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">idx</span> <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">0</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ----------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // box 為 10 個元素且型別為 int 的 array, 所有元素的</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 初始值全部設定為 0 , array 為固定長度的線性容器;</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // vector 則為可變長度容器(Container)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ----------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"請輸入 10 個數值(可任意空白隔開):"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">while</span> (<span style="color: #61afef;">cin</span> <span style="color: #98c379;">>></span> <span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">at</span>(<span style="color: #abb2bf;">idx</span>)) {</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">idx</span><span style="color: #e06c75;">++</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">if</span> (<span style="color: #abb2bf;">idx</span> <span style="color: #e06c75;">==</span> <span style="color: #c678dd;">10</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">break</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ----------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 設定 box[0] ~ box[9] 共 10 個元素值, box.at(idx)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 也可以用 box[idx] 來表達,但使用 box.at(idx) 會比 </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // box[idx] 安全性高。因為 box.at(idx) 會執行邊界檢測,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 當索引超過 box 邊界, => 拋出異常:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // terminate called after throwing an instance of </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 'std::out_of_range' what(): array::at: __n </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // (which is 10) >= _Nm (which is 10)...</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 反之,使用 box[idx] 的方式,即便 idx 索引超過了 box</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 邊界,也能執行,但這樣卻隱藏了潛在的 bug 風險..</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 上述片段,可以將程式改寫成:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // if (idx == 12) {</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // break;</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // }</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 然後再去比對使用 box.at(idx) 及 box[idx] 的差異.</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ----------------------------------------------</span></span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -----------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">sort</span>(<span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">begin</span>()<span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">end</span>());</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"取前 10 個數值進行排序結果(小=>大):"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> (<span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">item</span> <span style="color: #abb2bf;">:</span> <span style="color: #abb2bf;">box</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">item</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" "</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">reverse</span>(<span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">begin</span>()<span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">box</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">end</span>());</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -----------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // sort, reverse 為 algorithm 類別中的兩個方法</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // sort 排序預設由小->大。若將其結果 reverse => 大->小</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -----------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"取前 10 個數值進行排序結果(大=>小):"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> (<span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">item</span> <span style="color: #abb2bf;">:</span> <span style="color: #abb2bf;">box</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">item</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" "</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">執行結果:</span></div><div><span style="font-size: x-small;"><span style="color: #61afef;">請輸入</span> <span style="color: #c678dd;">10</span> 個數值(可任意空白隔開):<span style="color: #c678dd;">43</span> <span style="color: #c678dd;">39</span> <span style="color: #c678dd;">97</span> <span style="color: #c678dd;">81</span> <span style="color: #c678dd;">56</span> <span style="color: #c678dd;">67</span> <span style="color: #c678dd;">33</span> <span style="color: #c678dd;">37</span> <span style="color: #c678dd;">10</span> <span style="color: #c678dd;">9</span> <span style="color: #c678dd;">1</span> <span style="color: #c678dd;">15</span> <span style="color: #c678dd;">3</span></span></div><div><span style="font-size: x-small;">取前 <span style="color: #c678dd;">10</span> 個數值進行排序結果(小<span style="color: #e06c75;">=></span>大):<span style="color: #c678dd;">9</span> <span style="color: #c678dd;">10</span> <span style="color: #c678dd;">33</span> <span style="color: #c678dd;">37</span> <span style="color: #c678dd;">39</span> <span style="color: #c678dd;">43</span> <span style="color: #c678dd;">56</span> <span style="color: #c678dd;">67</span> <span style="color: #c678dd;">81</span> <span style="color: #c678dd;">97</span></span></div><div><span style="font-size: x-small;">取前 <span style="color: #c678dd;">10</span> 個數值進行排序結果(大<span style="color: #e06c75;">=></span>小):<span style="color: #c678dd;">97</span> <span style="color: #c678dd;">81</span> <span style="color: #c678dd;">67</span> <span style="color: #c678dd;">56</span> <span style="color: #c678dd;">43</span> <span style="color: #c678dd;">39</span> <span style="color: #c678dd;">37</span> <span style="color: #c678dd;">33</span> <span style="color: #c678dd;">10</span> <span style="color: #c678dd;">9</span></span></div><br /></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-28709946628307637642020-11-02T23:11:00.005+08:002020-11-02T23:22:08.166+08:00閒談C++(16):再論中英混合字串之切割 - 從 Big5 編碼下手面對中英混合字串,曾想過從 UTF-8 一路穿越: 程式原始檔(<span style="color: #cc0000;">檔案儲存 UTF-8</span>) => 執行階段(<span style="color: #2b00fe;">-fexec-charset=utf-8</span>) => 介面控制台輸出(<span style="color: #741b47;">CMD設定 chcp 65001</span>) ,但這一切似乎沒有想像中的單純容易,就以 Windows 8.1 而言,控制台輸出 CMD 在 chcp 65001 下,就中文字串實作來說就相當詭異,即便<span style="color: #cc0000; font-size: medium;"> cout </span>輸出中文 ok, 但利用 <span style="color: #351c75; font-size: medium;">getline(cin, data)</span> 的方式來抓取中文字串就不給力了!!<div>然而若是調整一下解決策略:程式原始檔(<span style="color: #cc0000;">檔案儲存 UTF-8</span>) => 執行階段(<span style="color: #2b00fe;">-fexec-charset=Big5</span>) => 介面控制台輸出(<span style="color: #741b47;">CMD設定 chcp 950</span>) 則不管是透過<span style="color: #2b00fe; font-size: medium;"> getline </span>、<span style="color: #741b47; font-size: medium;">cin</span> 的方式抓取輸入的中文字串或 <span style="color: #cc0000; font-size: medium;">cout</span> 輸出中文字串,就一切正常了 !! </div><div>剩下所需處理的問題就是:如何判定一連串中英數混合字串中,中文字該如何被擷取,換言之,在一連串的<span style="color: #990000; font-size: large;"> Bytes</span> 資料堆裡,辨識何者為中文字,何者非中文字...<br /><br /></div><div>程式檔案存檔:<span style="color: #0b5394;"><b>UTF-8</b></span></div><div>程式編譯參數:<span style="font-size: medium;"><span style="color: #800180;">-std=c++11</span> <span style="color: #2b00fe;">-finput-charset=utf-8 </span> <span style="color: #cc0000;">-fexec-charset=cp950</span></span></div><div><span style="color: #444444; font-size: medium;">Windows 8.1 CMD:</span><span style="color: #cc0000; font-size: medium;">chcp 950</span></div><div><br /></div><div><div style="background-color: #282c34; color: #bbbbbb; font-family: "Source Code Pro", Consolas, "Courier New", monospace; line-height: 20px; white-space: pre;"><div><span style="color: #e06c75; font-size: small;">#include</span><span style="font-size: small;"> </span><span style="color: #e5c07b; font-size: small;"><string></span><span style="font-size: small;"> </span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><iostream></span> </span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><vector></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">using</span> <span style="color: #56b6c2;">namespace</span> std; </span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> <span style="color: #98c379;">main</span>() { </span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">string</span> <span style="color: #abb2bf;">data</span> <span style="color: #e06c75;">=</span> <span style="color: #e5c07b;">""</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">vector</span><span style="color: #e06c75;"><</span><span style="color: #61afef;">string</span><span style="color: #e06c75;">></span> <span style="color: #abb2bf;">idxString</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">cnt</span> <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">0</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">short</span> <span style="color: #abb2bf;">byteValue</span> <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">0</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"請輸入:"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">getline</span>(<span style="color: #61afef;">cin</span><span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">data</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"字串總長度:"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">data</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">length</span>() <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> //</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"字串之各 byte 值:"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> (<span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">i</span><span style="color: #e06c75;">=</span><span style="color: #c678dd;">0</span>; <span style="color: #abb2bf;">i</span><span style="color: #e06c75;"><</span><span style="color: #abb2bf;">data</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">length</span>(); <span style="color: #abb2bf;">i</span><span style="color: #e06c75;">++</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">hex</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">uppercase</span><span style="color: #98c379;"><<</span> (<span style="color: #56b6c2;">short</span>(<span style="color: #abb2bf;">data</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">at</span>(<span style="color: #abb2bf;">i</span>)) <span style="color: #e06c75;">&</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">00FF</span>) <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" "</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // --------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // Big5 每個中文字使用 2 bytes。第一個 byte 範圍為 0xA4-0xF9,而第二個</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // byte 為 0x40-0x7E, 0xA1-0xFE</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // --------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // data.at(i) 取得 1 byte 的 char 資料,再將其強迫轉型為 2 bytes 的</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // short,接續進行與 0x00FF 資料的 bit-and 運算,其目的在於保留低位元組</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 部分,最後利用 << hex << uppercase 轉十六進位數值且以大寫字母輸出結果</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 註:是否為中文字的第 1 byte => 可藉由 (short(data.at(i)) & 0x00FF)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 取值判斷是否大於等於 0xA4(164) 且小於等於 0xF9(249)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // --------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> (<span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">i</span><span style="color: #e06c75;">=</span><span style="color: #c678dd;">0</span>; <span style="color: #abb2bf;">i</span><span style="color: #e06c75;"><</span><span style="color: #abb2bf;">data</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">length</span>(); <span style="color: #abb2bf;">i</span><span style="color: #e06c75;">++</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">byteValue</span> <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">short</span>(<span style="color: #abb2bf;">data</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">at</span>(<span style="color: #abb2bf;">i</span>)) <span style="color: #e06c75;">&</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">00FF</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">if</span> (<span style="color: #abb2bf;">byteValue</span> <span style="color: #e06c75;">>=</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">A4</span> <span style="color: #e06c75;">&&</span> <span style="color: #abb2bf;">byteValue</span> <span style="color: #e06c75;"><=</span> <span style="color: #e06c75;">0x</span><span style="color: #c678dd;">F9</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">idxString</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">push_back</span>(<span style="color: #abb2bf;">data</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">substr</span>(<span style="color: #abb2bf;">i</span><span style="color: #e06c75;">++</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">2</span>));</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // i++;</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ----------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // idxString 為 vector<string> 型別,把切割出來的字元</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 依序 push 到 vector 中,若遇見符合 2 bytes 組成中文</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 字時,=> data.substr(i++, 2) </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 也就是 data.substr(i, 2) 先取連續 2 bytes 子字串,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 而後再作 i++</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ----------------------------------------------</span></span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">else</span> {</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">idxString</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">push_back</span>(<span style="color: #abb2bf;">data</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">substr</span>(<span style="color: #abb2bf;">i</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">1</span>));</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // Big5碼線上查:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // http://billor.chsh.chc.edu.tw/php/Tools/qBig5.php</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://www.cns11643.gov.tw/searchQ.jsp?ID=0</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://ace33022.github.io/big5code/</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> //</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 以上得知,判斷是否為 Big5 編碼字元(中文字),只要判斷第一個 byte</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 是否落在 0xA4-0xF9 (十進位相當於 164~249)範圍,若是,則再取往</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 後一個 byte 來取碼並組合即可。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 註:這裡所談字元已非程式中定義的 char 型別之謂,乃泛指一個中文字、</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 一個英文字母、一個數字(0~9) 或一個符號(!,$, %, @) 等等。一個字</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 元的長度可以是 1 byte(英數符號), 或 2 bytes(Big5 編碼之中文字)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"利用 for range 輸出切割後單一字元內容:"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> (<span style="color: #56b6c2;">auto</span> <span style="color: #abb2bf;">s</span> <span style="color: #abb2bf;">:</span> <span style="color: #abb2bf;">idxString</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">s</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"|"</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"利用 at(i) 索引方式輸出切割後單一字元內容:"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> (<span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">i</span><span style="color: #e06c75;">=</span><span style="color: #c678dd;">0</span>; <span style="color: #abb2bf;">i</span><span style="color: #e06c75;"><</span><span style="color: #abb2bf;">idxString</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">size</span>(); <span style="color: #abb2bf;">i</span><span style="color: #e06c75;">++</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">idxString</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">at</span>(<span style="color: #abb2bf;">i</span>) <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"|"</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">執行結果:</span></div><div><span style="color: #61afef;"><span style="font-size: x-small;">請輸入:中文ABC123編碼</span></span></div><div><span style="font-size: x-small;">字串總長度:<span style="color: #c678dd;">14</span></span></div><div><span style="font-size: x-small;">字串之各 byte 值:</span></div><div><span style="font-size: x-small;">A4 A4 A4 E5 <span style="color: #c678dd;">41</span> <span style="color: #c678dd;">42</span> <span style="color: #c678dd;">43</span> <span style="color: #c678dd;">31</span> <span style="color: #c678dd;">32</span> <span style="color: #c678dd;">33</span> BD <span style="color: #c678dd;">73</span> BD <span style="color: #c678dd;">58</span></span></div><div><span style="font-size: x-small;">利用 <span style="color: #e06c75;">for</span> range 輸出切割後單一字元內容:</span></div><div><span style="font-size: x-small;">中<span style="color: #e06c75;">|</span>文<span style="color: #e06c75;">|</span>A<span style="color: #e06c75;">|</span>B<span style="color: #e06c75;">|</span>C<span style="color: #e06c75;">|</span><span style="color: #c678dd;">1</span><span style="color: #e06c75;">|</span><span style="color: #c678dd;">2</span><span style="color: #e06c75;">|</span><span style="color: #c678dd;">3</span><span style="color: #e06c75;">|</span>編<span style="color: #e06c75;">|</span>碼<span style="color: #e06c75;">|</span></span></div><div><span style="font-size: x-small;">利用 <span style="color: #98c379;">at</span>(i) 索引方式輸出切割後單一字元內容:</span></div><div><span style="font-size: x-small;">中<span style="color: #e06c75;">|</span>文<span style="color: #e06c75;">|</span>A<span style="color: #e06c75;">|</span>B<span style="color: #e06c75;">|</span>C<span style="color: #e06c75;">|</span><span style="color: #c678dd;">1</span><span style="color: #e06c75;">|</span><span style="color: #c678dd;">2</span><span style="color: #e06c75;">|</span><span style="color: #c678dd;">3</span><span style="color: #e06c75;">|</span>編<span style="color: #e06c75;">|</span>碼<span style="color: #e06c75;">|</span></span></div></div></div><div><br /></div><div>利用線上「<a href="https://ace33022.github.io/big5code/" target="_blank">中文字轉Big5碼</a>」驗證一下所輸入的中文字 Big5 碼,以下轉碼截圖:</div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-RVvl5uUuJ1w/X6AhUnJr9eI/AAAAAAAAUpc/EQPUpA0VK1wfAZPCRC-3xFzaB2-EOMqRwCLcBGAsYHQ/s646/big5.jpg" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="277" data-original-width="646" src="https://1.bp.blogspot.com/-RVvl5uUuJ1w/X6AhUnJr9eI/AAAAAAAAUpc/EQPUpA0VK1wfAZPCRC-3xFzaB2-EOMqRwCLcBGAsYHQ/s16000/big5.jpg" /></a></div><br /><div><br /></div><div> </div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-30250496469639507292020-10-31T23:43:00.009+08:002020-11-01T16:38:05.162+08:00閒談C++(15):中英混合字串切割及取子字串 - 搭 wstring 字元之橋, 而行 unicode 碼點轉 UTF-8 編碼在標準C++範疇,中文字串處理一直是個難越過的檻,尤其是中英數字夾雜的字串堆裡,欲切割字元或取子字串都是件費心費力的事,以下為近期心得,筆記於此.<div>建議先行理解甚麼是 unicode, 何謂 UTF-8編碼,所謂的中文亂碼,通常導因於執行環境(ex : windows CMD 模式下之 code page 950 或 UTF-8)與程式撰寫(原始碼程式檔案本身的編碼,ex:Big5 或 UTF-8)所採用編碼不同所致,建議以下幾篇文章可以詳閱(尤其是<a href="https://openhome.cc/Gossip/">林信良</a>(良葛格)先生的幾篇文章相當精采):</div><div>0. <a href="https://openhome.cc/Gossip/Encoding/">非關語言: 亂碼 1/2</a></div><div>1. <a href="https://openhome.cc/Gossip/Encoding/UnicodeUTF.html">Unicode 與 UTF</a> </div><div>2. <a href="https://www.ithome.com.tw/voice/135711">C++與Unicode</a></div><div>3. <a href="https://openhome.cc/Gossip/CppGossip/string2.html">使用 string</a></div><div>4. <a href="https://openhome.cc/Gossip/CppGossip/string1.html">字元陣列與字串</a></div><div><br /></div><div>此外,網路有篇文章專論各種編碼,清晰可讀:</div><div><a href="https://www.mdeditor.tw/pl/pUWb/zh-tw">深入理解字元編碼(ASCII、Unicode、UTF-8、UTF-16、UTF-32)</a></div><div><br /></div><div>以下程式執行相關環境設定:</div><div>1. windows 8.1</div><div>2. 程式編譯 g++ (MinGW-W64 8.1.0)</div><div>3. 編譯參數:g++ <span style="color: #274e13;">-<span style="font-size: medium;">std=c++11</span></span> $fileName -o $fileNameWithoutExt <span style="color: #cc0000; font-size: medium;">-finput-charset=utf-8</span> <span style="color: #351c75; font-size: medium;">-fexec-charset=utf-8</span> && $dir$fileNameWithoutExt"</div><div>4. VSCode 編輯 C++ 程式之文件編碼 <span style="color: #990000; font-size: medium;">UTF-8</span></div><div>5. 使用 <a href="https://cmder.net/">cmder</a> 環境執行本程式,並設定 code page 為 <span style="color: #990000; font-size: medium;">UTF-8 => chcp 65001</span></div><div><br /></div><div><div style="background-color: #282c34; color: #bbbbbb; font-family: "Source Code Pro", Consolas, "Courier New", monospace; line-height: 20px; white-space: pre;"><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><locale></span> </span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><codecvt></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><string></span> </span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><iostream></span> </span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">using</span> <span style="color: #56b6c2;">namespace</span> std; </span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> <span style="color: #98c379;">main</span>() { </span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">wstring_convert</span><span style="color: #e06c75;"><</span><span style="color: #61afef;">codecvt_utf8_utf16</span><span style="color: #e06c75;"><</span><span style="color: #56b6c2;">wchar_t</span><span style="color: #e06c75;">>></span> <span style="color: #abb2bf;">cvt</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">string</span> <span style="color: #abb2bf;">stdStr</span> <span style="color: #e06c75;">=</span> <span style="color: #e5c07b;">"AB中文CD字"</span>; </span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">wstring</span> <span style="color: #abb2bf;">stdWStr</span> <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">cvt</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">from_bytes</span>(<span style="color: #abb2bf;">stdStr</span>);<span style="color: #676f7d;"> // string->wstring</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // stdStr 為標準庫 string 字串,內含中英混合字串,欲從其中切割字元,實屬不易,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // => 先將 string 轉換成 wstring , 可利用以下轉換函數:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // wstring_convert<codecvt_utf8_utf16<wchar_t>>().from_bytes()</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // .from_bytes() 之參數為 std::string,其回傳值為 std::wstring</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // .to_bytes() 之參數為 std::wstring,其回傳值為 std::string</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // wstring_convert<codecvt_utf8_utf16<wchar_t>> : wstring <-> utf-8 </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 這 wstring 即所謂的寬字串,所儲存的是 unicode 字元的碼點(code point),但</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 絕非指「UTF-8 編碼」。碼點指的是字元編號(如同ASCII字元集,'A'的編號為十進位</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 的 65, 此處不言編碼而言編號,意欲分判清楚),何義呢?所謂的碼點就是 unicode</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 字元集裡所賦予每個 unicode 字元一個唯一的編號(例如:「中」的 unicode 碼點為</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 十進位的 20013,相當於十六進位的 0x4E2D)。再次強調:碼點是編號而不是編碼形式,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 而若要將此 unicode 字元碼點(編號) 用不同的形式予以表達,如 UTF-8, UTF-16</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 甚或 UTF-32 等,這就涉及所謂的編碼問題了。所以切記,unicode 字元的碼點也就僅</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 僅是個編號而已,絕非指編碼 ! 故即便透過標準輸出介面任憑如何設定編碼格式(UTF-8,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // big5..),如若是 wstring,中文字部分就是無法顯示,那為何英文字能正常顯示呢?</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 原因就是英數字、符號等 ASCII 字元之 UTF-8 編碼恰與其 ASCII 編碼相同,故在輸</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 出介面利用指令: chcp 65001 後之 UTF-8 code page 檢視下就能正常顯示;反之,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 中文字原非屬 ASCII 編碼下的字元,因此無法顯示。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -----------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"原始字串:"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">stdStr</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"依序遞增取原始字串之子字串:"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">lh</span> <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">stdWStr</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">length</span>();</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> (<span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">i</span><span style="color: #e06c75;">=</span><span style="color: #c678dd;">0</span>; <span style="color: #abb2bf;">i</span><span style="color: #e06c75;"><</span><span style="color: #abb2bf;">lh</span>; <span style="color: #abb2bf;">i</span><span style="color: #e06c75;">++</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">string</span> <span style="color: #abb2bf;">ss</span> <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">cvt</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">to_bytes</span>(<span style="color: #abb2bf;">stdWStr</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">substr</span>(<span style="color: #c678dd;">0</span><span style="color: #abb2bf;">,</span> <span style="color: #abb2bf;">i</span><span style="color: #e06c75;">+</span><span style="color: #c678dd;">1</span>));<span style="color: #676f7d;"> // wstring->string</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">ss</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -----------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 使用標準函式庫 之 string ,當如有中英文混合時,則無法調用 .at(i) 方法正確</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 取出每一個字元(英文字、數字及中文字分別視為單一字元),原因在於當程式碼原始檔</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 若採用 UTF-8 編碼時,英數字各佔位一個 byte, 但中文字則佔 3 bytes, 此時調</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 用 .at(i) 或 [i] 一次只能取出一個 byte 資料,對於中英文夾雜之字串,難以正</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 確切割進而正確取值。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 但若採用 wstring 則可以利用 .at(i) 或 [i] 的方式取出單一字元的碼點(注意:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 是碼點,而不是 UTF-8 編碼資料),因為 wstring 所儲存格式為字元之 unicode </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 碼點(code point),白話的說就是編號,該如何將此碼點轉換成 UTF-8 編碼資料呢?</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 可以利用 wstring_convert<codecvt_utf8_utf16<wchar_t>> 轉換器進行轉換</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 編碼,這來自 C++11,故需要 #include <locale> 及 #include <codecvt> </span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 此外,也可以對 wstring 進行子字串調用 => substr(i, n) ,取出子字串後再進</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 行轉編碼成 UTF-8 => 在 65001 code page 下就可正常顯示中文了..</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 結論:string 無法單就中英文混合字串進行索引及調用子字串,=> 善用 wstring</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 註:string substr(size_t pos = 0, size_t len = npos)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ex : ss.substr(2, 3) => 從字串 ss 之索引 2 的位置開始取連續 3 個字元</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -----------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"------------------------------------------"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"原始字串:"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">stdStr</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"以下輸出各字元之 UTF-8 編碼長度:"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">string</span> <span style="color: #abb2bf;">ss</span> <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">cvt</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">to_bytes</span>(<span style="color: #abb2bf;">stdWStr</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> (<span style="color: #56b6c2;">int</span> <span style="color: #abb2bf;">i</span><span style="color: #e06c75;">=</span><span style="color: #c678dd;">0</span>; <span style="color: #abb2bf;">i</span><span style="color: #e06c75;"><</span><span style="color: #abb2bf;">lh</span>; <span style="color: #abb2bf;">i</span><span style="color: #e06c75;">++</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">string</span> <span style="color: #abb2bf;">ss</span> <span style="color: #e06c75;">=</span> <span style="color: #abb2bf;">cvt</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">to_bytes</span>(<span style="color: #abb2bf;">stdWStr</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">substr</span>(<span style="color: #abb2bf;">i</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">1</span>));<span style="color: #676f7d;"> // wstring->string</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">ss</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">length</span>() <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">" "</span>;</span></div><div><span style="font-size: x-small;"> } </span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -----------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"------------------------------------------"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"「"</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">stdStr</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"」各字元之碼點(code point, 十進位):"</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> (<span style="color: #56b6c2;">auto</span> <span style="color: #abb2bf;">ch</span> <span style="color: #abb2bf;">:</span> <span style="color: #abb2bf;">stdWStr</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">ch</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> }</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -----------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">執行結果:</span></div><div><span style="color: #61afef;"><span style="font-size: x-small;">原始字串:AB中文CD字</span></span></div><div><span style="font-size: x-small;">依序遞增取原始字串之子字串:</span></div><div><span style="font-size: x-small;">A</span></div><div><span style="font-size: x-small;">AB</span></div><div><span style="font-size: x-small;">AB中</span></div><div><span style="font-size: x-small;">AB中文</span></div><div><span style="font-size: x-small;">AB中文C</span></div><div><span style="font-size: x-small;">AB中文CD</span></div><div><span style="font-size: x-small;">AB中文CD字</span></div><div><span style="color: #e06c75;"><span style="font-size: x-small;">------------------------------------------</span></span></div><div><span style="font-size: x-small;">原始字串:AB中文CD字</span></div><div><span style="font-size: x-small;">以下輸出各字元之 UTF<span style="color: #e06c75;">-</span><span style="color: #c678dd;">8</span> 編碼長度:</span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">1</span> <span style="color: #c678dd;">1</span> <span style="color: #c678dd;">3</span> <span style="color: #c678dd;">3</span> <span style="color: #c678dd;">1</span> <span style="color: #c678dd;">1</span> <span style="color: #c678dd;">3</span></span></div><div><span style="color: #e06c75;"><span style="font-size: x-small;">------------------------------------------</span></span></div><div><span style="font-size: x-small;">「AB中文CD字」各字元之碼點(code point<span style="color: #abb2bf;">,</span> 十進位):</span></div><div><span style="color: #c678dd;"><span style="font-size: x-small;">65</span></span></div><div><span style="color: #c678dd;"><span style="font-size: x-small;">66</span></span></div><div><span style="color: #c678dd;"><span style="font-size: x-small;">20013</span></span></div><div><span style="color: #c678dd;"><span style="font-size: x-small;">25991</span></span></div><div><span style="color: #c678dd;"><span style="font-size: x-small;">67</span></span></div><div><span style="color: #c678dd;"><span style="font-size: x-small;">68</span></span></div><div><span style="color: #c678dd;"><span style="font-size: x-small;">23383</span></span></div></div></div><div><br /></div><div>cmder 環境下執行之截圖:<br /><br /></div><table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left;"><tbody><tr><td style="text-align: center;"><a href="https://1.bp.blogspot.com/-KTyb4X1vCQU/X52FbtQdunI/AAAAAAAAUos/bxY4EGXhLZsQ_tv6Wblr-PWX6hhyA1KPwCLcBGAsYHQ/s553/cmder.jpg" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="507" data-original-width="553" src="https://1.bp.blogspot.com/-KTyb4X1vCQU/X52FbtQdunI/AAAAAAAAUos/bxY4EGXhLZsQ_tv6Wblr-PWX6hhyA1KPwCLcBGAsYHQ/s16000/cmder.jpg" /></a></td></tr><tr><td class="tr-caption" style="text-align: center;"><br /></td></tr></tbody></table><br /><div><br /></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-90773114648552699482020-10-18T16:32:00.005+08:002020-11-17T22:49:10.387+08:00閒談C++(14):淺談類別, private, public, this指標<div style="background-color: #282c34; color: #bbbbbb; font-family: "Source Code Pro", Consolas, "Courier New", monospace; line-height: 20px; white-space: pre;"><div><span style="font-size: x-small;"><span style="color: #e06c75;">#include</span> <span style="color: #e5c07b;"><iostream></span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">using</span> <span style="color: #56b6c2;">namespace</span> std;</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"><span style="color: #56b6c2;">class</span> <span style="color: #61afef;">Person</span> {</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">public</span><span style="color: #abb2bf;">:</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">string</span> <span style="color: #abb2bf;">id</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">string</span> <span style="color: #abb2bf;">name</span>;</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">public</span><span style="color: #abb2bf;">:</span></span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">Person</span>(<span style="color: #61afef;">string</span><span style="color: #abb2bf;">,</span> <span style="color: #61afef;">string</span>);<span style="color: #676f7d;"> /// 建構函數不能有回傳值</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">string</span> <span style="color: #98c379;">getInfo</span>();</span></div><div><span style="font-size: x-small;"> <span style="color: #56b6c2;">void</span> <span style="color: #98c379;">updateInfo</span>(<span style="color: #61afef;">string</span><span style="color: #abb2bf;">,</span> <span style="color: #61afef;">string</span>);</span></div><div><span style="font-size: x-small;">};</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;">/// 上述為 Person 類別的宣告</span></span></div><div><span style="font-size: x-small;"><span style="color: #61afef;">Person</span><span style="color: #abb2bf;">::</span><span style="color: #98c379;">Person</span>(<span style="color: #61afef;">string</span> <span style="color: #d19a66; font-style: italic;">id</span><span style="color: #abb2bf;">,</span> <span style="color: #61afef;">string</span> <span style="color: #d19a66; font-style: italic;">name</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">this</span><span style="color: #abb2bf;">-></span><span style="color: #abb2bf;">id</span> <span style="color: #98c379;">=</span> <span style="color: #d19a66; font-style: italic;">id</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">this</span><span style="color: #abb2bf;">-></span><span style="color: #abb2bf;">name</span> <span style="color: #98c379;">=</span> <span style="color: #d19a66; font-style: italic;">name</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // ----------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 變數命名有時很費心思,這裡簡化令參數名稱與資料成員名稱</span></span><span style="color: #676f7d; font-size: small;">一致</span><span style="color: #676f7d; font-size: small;">,但如何區分</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 參數與資料成員呢? => 利用 this 指標.</span></span></div><div><div style="line-height: 20px;"><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // this 是一個指標,而且隱含於類別成員函數之中. this 指向調用該成員函數之</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 物件自身,也就是該物件本身資料成員區塊在記憶體中的位址。若以類別衍生多個</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 物件言,不同物件各自擁有一份資料成員;然成員函數也就僅僅一份。至於同樣一</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 份成員函數又如何處理多份物件各自擁有的資料成員呢?答案就是「this」指標。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 緣此,當一個物件調用其成員函數時,編譯器會將目前該物件資料成員所在的記憶</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 體位址隱式地傳遞給成員函數中的 this 指標,當此,成員函數中的 this 指標</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 即指向該物件。簡言之,this 指標隱含於成員函數中,它用來指向調用它的物件。</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 參考:</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://openhome.cc/Gossip/CppGossip/thisPointer.html</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://www.bogotobogo.com/cplusplus/this_pointer.php</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // https://docs.microsoft.com/zh-tw/cpp/cpp/this-pointer?view=msvc-160</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // PS:資料成員 (data member)、成員函數 (member function)</span></span></div></div></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"><span style="color: #61afef;">string</span> <span style="color: #61afef;">Person</span><span style="color: #abb2bf;">::</span><span style="color: #98c379;">getInfo</span>() {</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">return</span> <span style="color: #e5c07b;">"姓名:"</span> <span style="color: #98c379;">+</span> <span style="color: #abb2bf;">name</span> <span style="color: #98c379;">+</span> <span style="color: #e5c07b;">",ID:"</span> <span style="color: #98c379;">+</span> <span style="color: #abb2bf;">id</span>;</span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"><span style="color: #56b6c2;">void</span> <span style="color: #61afef;">Person</span><span style="color: #abb2bf;">::</span><span style="color: #98c379;">updateInfo</span>(<span style="color: #61afef;">string</span> <span style="color: #d19a66; font-style: italic;">id</span><span style="color: #abb2bf;">,</span> <span style="color: #61afef;">string</span> <span style="color: #d19a66; font-style: italic;">name</span>) {</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">this</span><span style="color: #abb2bf;">-></span><span style="color: #abb2bf;">id</span> <span style="color: #98c379;">=</span> <span style="color: #d19a66; font-style: italic;">id</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">this</span><span style="color: #abb2bf;">-></span><span style="color: #abb2bf;">name</span> <span style="color: #98c379;">=</span> <span style="color: #d19a66; font-style: italic;">name</span>;</span></div><div><span style="font-size: x-small;">}</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;">// ------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;">// :: => 範圍解析運算子,用來類別外部定義成員函數之用..</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;">// ------------------------------------------------</span></span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">int</span> <span style="color: #98c379;">main</span>() {</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">Person</span> <span style="color: #abb2bf;">p1</span>(<span style="color: #e5c07b;">"Q12345"</span><span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">"小強"</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">p1</span><span style="color: #abb2bf;">.</span><span style="color: #abb2bf;">id</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>; </span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">p1</span><span style="color: #abb2bf;">.</span><span style="color: #abb2bf;">name</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -----------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 要直接存取物件中的資料成員,一定要在成員前方冠上 public,</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 若沒有的話預設值是 private,若是 private => p1.id</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 會出現 error.. 類似:error: 'std::__cxx11::string</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // Person::name' is private within this context</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 這裡只是實驗性質,基於物件導向封裝(Encapsulation)的特</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 性,理應將 id, name 設定為 private 才是. 至於如何調</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 用 id, name => 透過成員函數(通常設定為 public)</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -----------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // private : 簡單來說,只能透過成員函數予以調用,此外,在</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // 類別成員未指定其權限時,預設就是 private</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // public : 可以被任何看得到它的物件實體存取</span></span></div><div><span style="color: #676f7d;"><span style="font-size: x-small;"> // -----------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">p1</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">getInfo</span>();</span></div><div><span style="font-size: x-small;"> <span style="color: #abb2bf;">p1</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">updateInfo</span>(<span style="color: #e5c07b;">"Q36745"</span><span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">"大強"</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #e5c07b;">"資料更新後..."</span> <span style="color: #98c379;"><<</span> <span style="color: #98c379;">endl</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #61afef;">cout</span> <span style="color: #98c379;"><<</span> <span style="color: #abb2bf;">p1</span><span style="color: #abb2bf;">.</span><span style="color: #98c379;">getInfo</span>();</span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="color: #61afef;"><span style="font-size: x-small;">執行結果:</span></span></div><div><span style="color: #61afef;"><span style="font-size: x-small;">Q12345</span></span></div><div><span style="font-size: x-small;">小強</span></div><div><span style="font-size: x-small;">姓名:小強,ID:Q12345</span></div><div><span style="font-size: x-small;">資料更新後...</span></div><div><span style="font-size: x-small;">姓名:大強,ID:Q36745</span></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-5885217093298941662020-10-07T11:00:00.004+08:002020-10-07T11:04:05.528+08:00揮灑Python(70):二元搜尋樹(Binary Search Tree)<div style="background-color: #282c34; color: #bbbbbb; line-height: 20px; white-space: pre;"><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">import</span> random</span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;">#</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #56b6c2;">class</span> <span style="color: #61afef;">Node</span>:</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;">#</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #56b6c2;">def</span> <span style="color: #98c379;">__init__</span>(<span style="color: #d19a66; font-style: italic;">self</span><span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">data</span>):</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>data <span style="color: #e06c75;">=</span> data</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>left <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">None</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>right <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">None</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># -----------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #56b6c2;">def</span> <span style="color: #98c379;">insertNode</span>(<span style="color: #d19a66; font-style: italic;">self</span><span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">data</span>):</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> </span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">if</span> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>data<span style="color: #abb2bf;">:</span> <span style="color: #676f7d;"># 表示 self.data 不為 None</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">if</span> data <span style="color: #e06c75;"><</span> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>data<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">if</span> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>left <span style="color: #e06c75;">is</span> <span style="color: #56b6c2;">None</span><span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>left <span style="color: #e06c75;">=</span> Node(data)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">else</span><span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>left<span style="color: #abb2bf;">.</span>insertNode(data)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># --------------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 因為此時 self.left is not None, 代表 self.left 已經指派一個 Node</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 節點了,也就是說,self.left 本身就是一個 Node 節點,既已是 Node 實例</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># (instance),當然可以 call 成員函式 insertNode() </span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># -------------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">else</span><span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">if</span> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>right <span style="color: #e06c75;">is</span> <span style="color: #56b6c2;">None</span><span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>right <span style="color: #e06c75;">=</span> Node(data)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">else</span><span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>right<span style="color: #abb2bf;">.</span>insertNode(data)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">else</span><span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>data <span style="color: #e06c75;">=</span> data</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># -------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #56b6c2;">def</span> <span style="color: #98c379;">printTreeInorder</span>(<span style="color: #d19a66; font-style: italic;">self</span>):</span></div><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">if</span> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>left<span style="color: #abb2bf;">: # L</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>left<span style="color: #abb2bf;">.</span>printTreeInorder()</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># ---------------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 注意:if self.left 若為 True,表當前的 Node 有左節點,此時 self.left</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 是個不折不扣的 Node 實體,因此當調用 printTreeInorder(),也就是執行</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># self.left.printTreeInorder() 時,則產生一次遞迴呼叫,一旦進入該函數</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># printTreeInorder() 後,第一時間又再次作 if self.left 判斷,如此在沒有</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 如 C/C++ 的指標結構下,Python 依然可以完成二元樹之左分支節點遞迴走訪..</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># --------------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>data<span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">end</span><span style="color: #e06c75;">=</span><span style="color: #e5c07b;">" "</span>) # D</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># ------------------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 中序追蹤(Inorder)的次第為:LDR => Left-Subtree/Root/Right-Subtree</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 也就是:左子樹-根節點-右子樹。當遞迴追蹤左子樹直到不再遞迴時,代表目前所在節點</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 已無左子樹節點,則按「左-根-右」法則,=> 左子已無 => 直接輸出目前所在節點資料</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># (也就是「根」,self.data) => 接續右子樹,右子樹之追蹤如下所示..</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># ------------------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">if</span> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>right<span style="color: #abb2bf;">: # R</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">self</span><span style="color: #abb2bf;">.</span>right<span style="color: #abb2bf;">.</span>printTreeInorder()</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># ---------------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 注意:if self.right 若為 True,表當前的 Node 有右節點,此時 self.right</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 是個不折不扣的 Node 實體,因此當調用 printTreeInorder(),也就是執行</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># self.right.printTreeInorder() 時,則產生一次遞迴呼叫,一旦進入該函數</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># printTreeInorder() ,第一時間又再次作 if self.left 判斷,如此之故在於</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 採用中序追蹤法則,中序法則為「左-根-右」,也就是遍歷尋訪以左子樹節點優先走訪,</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 一旦該作用節點再無左子樹,則直接輸出當前作用節點資料(根,self.data),後續則</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 再次 if self.right 判斷,如此在沒有如 C/C++ 的指標結構下,Python 依然可</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 以完成二元樹之右分支節點遞迴走訪..</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># --------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;">#</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">dataList <span style="color: #e06c75;">=</span> [x <span style="color: #e06c75;">for</span> x <span style="color: #e06c75;">in</span> <span style="color: #98c379;">range</span>(<span style="color: #c678dd;">1</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">200</span>)]</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">randData <span style="color: #e06c75;">=</span> random<span style="color: #abb2bf;">.</span>sample(dataList<span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">20</span>)</span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># ------------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># dataList 利用串列生成式(list comprehension) 產生1-199數值,</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># random.sample(dataList, 20) 於 dataList 中挑選20個不重複整數。</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># ------------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #56b6c2;">f</span><span style="color: #e5c07b;">"原始資料序列:</span><span style="color: #56b6c2;">\n{</span>randData<span style="color: #56b6c2;">}</span><span style="color: #e5c07b;">"</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">root <span style="color: #e06c75;">=</span> Node(randData[<span style="color: #c678dd;">0</span>])</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">for</span> i <span style="color: #e06c75;">in</span> <span style="color: #98c379;">range</span>(<span style="color: #c678dd;">1</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">20</span>)<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> root<span style="color: #abb2bf;">.</span>insertNode(randData[i])</span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;">#</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"</span><span style="color: #56b6c2;">\n</span><span style="color: #e5c07b;">資料經過二元搜尋樹(BST)建構且利用中序追蹤後之結果:"</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">root<span style="color: #abb2bf;">.</span>printTreeInorder()</span></div><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span><div><span style="font-family: Source Code Pro; font-size: x-small;">執行結果:</span></div><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span><div><span style="font-family: Source Code Pro; font-size: x-small;">原始資料序列:</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">[<span style="color: #c678dd;">195</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">10</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">173</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">23</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">169</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">17</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">1</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">96</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">66</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">40</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">131</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">65</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">59</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">45</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">80</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">105</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">148</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">127</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">41</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">166</span>]</span></div><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span><div><span style="font-family: Source Code Pro; font-size: x-small;">資料經過二元搜尋樹(<span style="color: #56b6c2;">BST</span>)建構且利用中序追蹤後之結果:</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #c678dd;">1</span> <span style="color: #c678dd;">10</span> <span style="color: #c678dd;">17</span> <span style="color: #c678dd;">23</span> <span style="color: #c678dd;">40</span> <span style="color: #c678dd;">41</span> <span style="color: #c678dd;">45</span> <span style="color: #c678dd;">59</span> <span style="color: #c678dd;">65</span> <span style="color: #c678dd;">66</span> <span style="color: #c678dd;">80</span> <span style="color: #c678dd;">96</span> <span style="color: #c678dd;">105</span> <span style="color: #c678dd;">127</span> <span style="color: #c678dd;">131</span> <span style="color: #c678dd;">148</span> <span style="color: #c678dd;">166</span> <span style="color: #c678dd;">169</span> <span style="color: #c678dd;">173</span> <span style="color: #c678dd;">195</span> </span></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-39623673263581249662020-10-06T10:55:00.009+08:002020-10-06T11:02:08.169+08:00揮灑Python(69):Tuple of List 之二進位檔案寫入及讀取(轉換函數:chr, ord, bytes, int.to_bytes, int.from_bytes)<div style="background-color: #282c34; color: #bbbbbb; line-height: 20px; white-space: pre;"><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># --------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 將 tuple of list 結構內容以二進位模式寫入檔案,接續再予以二進位</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 模式讀取,還原其內容值</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># --------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">import</span> random</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">import</span> os</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">import</span> time</span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;">#</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">startTime <span style="color: #e06c75;">=</span> time<span style="color: #abb2bf;">.</span>time()</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">tupList <span style="color: #e06c75;">=</span> []</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">for</span> i <span style="color: #e06c75;">in</span> <span style="color: #98c379;">range</span>(<span style="color: #c678dd;">1</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">27</span>)<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> tupList<span style="color: #abb2bf;">.</span>append((<span style="color: #98c379;">chr</span>(<span style="color: #c678dd;">64</span><span style="color: #e06c75;">+</span>i)<span style="color: #abb2bf;">,</span> random<span style="color: #abb2bf;">.</span>randint(<span style="color: #c678dd;">256</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">999</span>)))</span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;">#</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #56b6c2;">f</span><span style="color: #e5c07b;">"寫入檔案前之原始 tuple of list 內容:</span><span style="color: #56b6c2;">\n{</span>tupList<span style="color: #56b6c2;">}</span><span style="color: #e5c07b;">"</span>)</span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># --------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 利用 for 及 random 亂數函數,構建一個 tuple of list 結構。</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># random.randint(256, 999) => 亂數產生範圍包含上下限 256, 999</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># --------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># ※※※ 常用轉換函數說明 ※※※</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># chr() => 將整數轉換成字元, ex: chr(65) => A</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># ord() => 將字元轉換成整數, ex: ord("B") => 66</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># bin() => 將整數轉換成二進位0,1字串, ex: bin(123)=>0b1111011</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># hex() => 轉換成十六進制輸出, ex: hex(255) => 0xff ,但這只是</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 輸出呈現的方式,若要真正寫入二進位檔案,則要以 byte 的形式為之。</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 註:Python 中的 chr() 及 ord() 之字元及整數互轉,當中字元可擴展</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 至 Unicode。 chr(20013) => 中 , ord("中") => 20013</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># --------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># VSCode 之於 chr, ord 函數提示說明:</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># chr():Return a Unicode string of one character with </span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># ordinal i; 0 <= i <= 0x10ffff.</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># ord():Return the Unicode code point for a one-character</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># string.</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># --------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">with</span> <span style="color: #98c379;">open</span>(<span style="color: #e5c07b;">"test.bin"</span><span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">"wb"</span>) <span style="color: #e06c75;">as</span> tlFile<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">for</span> key<span style="color: #abb2bf;">,</span> value <span style="color: #e06c75;">in</span> tupList<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> tlFile<span style="color: #abb2bf;">.</span>write(<span style="color: #56b6c2;">bytes</span>([<span style="color: #98c379;">ord</span>(key)]))</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> tlFile<span style="color: #abb2bf;">.</span>write(value<span style="color: #abb2bf;">.</span>to_bytes(<span style="color: #c678dd;">2</span><span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">byteorder</span><span style="color: #e06c75;">=</span><span style="color: #e5c07b;">"big"</span>))</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># ------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># byteorder => Big-Endian 或 Little-Endian</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 例如:有一個 32 位元整數 0x12345678 採用 Big-Endian</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># => (低)記憶體位址 ---------------> (高)記憶體位址 </span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 資料序: 0x12 0x34 0x56 0x78</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># ------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># tlFile.write(bytes([ord(key)])) => 將 tupList 中</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 每個配對裡頭的字母 A, B, C,... 予以寫入,後頭接續</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># tlFile.write(value.to_bytes(2, byteorder="big"))</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 則是寫入配對裡頭的數值,整數轉 byte => to_bytes 函數</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 這裡數值均不大,因此轉成 2 bytes 即可,採用 Big-Endian</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># ------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># key 占 1 個 byte;value 占 2 bytes => 合占 3 bytes</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 又總共 10 組資料配對 => 10 x 3 = 30 bytes</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 故最後寫入二進位檔案共有 30 bytes 資料長度。</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># ------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">tlFile<span style="color: #abb2bf;">.</span>close()</span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># --------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 以下讀取 test.bin 二進位檔並剖析還原先前寫入tuple of list之資料</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># --------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">with</span> <span style="color: #98c379;">open</span>(<span style="color: #e5c07b;">"test.bin"</span><span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">"rb"</span>) <span style="color: #e06c75;">as</span> tlFile<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;">#</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> destTupList <span style="color: #e06c75;">=</span> []</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> eofTag <span style="color: #e06c75;">=</span> tlFile<span style="color: #abb2bf;">.</span>seek(<span style="color: #c678dd;">0</span><span style="color: #abb2bf;">,</span> os<span style="color: #abb2bf;">.</span><span style="color: #56b6c2;">SEEK_END</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> tlFile<span style="color: #abb2bf;">.</span>seek(<span style="color: #c678dd;">0</span><span style="color: #abb2bf;">,</span> os<span style="color: #abb2bf;">.</span><span style="color: #56b6c2;">SEEK_SET</span>) </span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># ----------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># eofTag = tlFile.seek(0, os.SEEK_END) 在設定檔尾位置。</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 開始讀取檔案時,記得把檔案指標拉到檔頭 =>seek(0, os.SEEK_SET) </span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># destTupList 準備用來構建源自二進位檔案內容之 (key, value)</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 配對所形成之 tuple of list </span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># ----------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #e06c75;">while</span> tlFile<span style="color: #abb2bf;">.</span>tell() <span style="color: #e06c75;"><</span> eofTag<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> key <span style="color: #e06c75;">=</span> tlFile<span style="color: #abb2bf;">.</span>read(<span style="color: #c678dd;">1</span>)<span style="color: #abb2bf;">.</span>decode(<span style="color: #e5c07b;">"ASCII"</span>) </span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> value <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">int</span><span style="color: #abb2bf;">.</span>from_bytes(tlFile<span style="color: #abb2bf;">.</span>read(<span style="color: #c678dd;">2</span>)<span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">byteorder</span><span style="color: #e06c75;">=</span><span style="color: #e5c07b;">"big"</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> destTupList<span style="color: #abb2bf;">.</span>append((key<span style="color: #abb2bf;">,</span> value))</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># ------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># fileObject.seek(offset [, whence ]) 解析:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># offset - 位移量,以 byte 為單位。 whence:可選,預設</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 值為 0;配合 offset 參數,whence 可有三種定義:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 0 => 相對檔案起始位置(檔頭)開始算起;os.SEEK_SET</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 1 => 相對檔案指標當前位置開始算起;os.SEEK_CUR</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 2 => 相對檔案結束位置(檔尾)開始算起;os.SEEK_END</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># ------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># eofTag = tlFile.seek(0, os.SEEK_END) => 回傳</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 檔尾的位置 => 想像一下這個位置就是 EOF => 也就是檔案最</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 後一個合法的 byte 資料的後一個位置。本例得到的 EOF=30</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># ------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># fileObject.tell() => 回傳目前檔案指標的位置。檔案開啟</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 時,預設檔案指標位置設定於 0 ,也就是檔頭(檔案資料的第 1</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 個 byte),當 read(1) => 讀取 1 個 byte 資料後,檔案</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 指標會自動往後移一個 byte 的位置, => tell() => 1</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># ------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 利用 read(n) 讀取 n bytes => 資料為 b'\x02 byte形式,</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 若為單一 byte, 可調用 decode("ASCII") 轉換成字元形式,</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 這裡的字元為 ASCII 字元,原則為 0-255 範圍..</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 若為多個 bytes,可按實際需求調用 int.from_bytes()函數.</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 先前將整數值寫入二進位檔案時,整數值之明確範圍:256-999</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 故決採 2 bytes 長度寫入此整數值,並以 Big-Endian 模式。</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># 反之,讀取檔案時,亦該連續讀取 2 bytes 資料並採用 Big-</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># Endian 模式將此 2 bytes 資料予以還原轉換成原整數值。</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #676f7d;"># ------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #56b6c2;">f</span><span style="color: #e5c07b;">"</span><span style="color: #56b6c2;">\n</span><span style="color: #e5c07b;">讀取來自檔案所建構之 tuple of list 內容:</span><span style="color: #56b6c2;">\n{</span>destTupList<span style="color: #56b6c2;">}</span><span style="color: #e5c07b;">"</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">tlFile<span style="color: #abb2bf;">.</span>close()</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">endTime <span style="color: #e06c75;">=</span> time<span style="color: #abb2bf;">.</span>time()</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #56b6c2;">f</span><span style="color: #e5c07b;">"</span><span style="color: #56b6c2;">\n</span><span style="color: #e5c07b;">執行時間:</span><span style="color: #56b6c2;">{</span><span style="color: #98c379;">round</span>(endTime<span style="color: #e06c75;">-</span>startTime<span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">5</span>)<span style="color: #56b6c2;">}</span><span style="color: #e5c07b;"> 秒"</span>)</span></div><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span><div><span style="font-family: Source Code Pro; font-size: x-small;">執行結果:</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">寫入檔案前之原始 <span style="color: #56b6c2;">tuple</span> of <span style="color: #56b6c2;">list</span> 內容:</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">[(<span style="color: #e5c07b;">'A'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">729</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'B'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">801</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'C'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">588</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'D'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">409</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'E'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">776</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'F'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">393</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'G'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">834</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'H'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">484</span>)<span style="color: #abb2bf;">,</span> </span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">(<span style="color: #e5c07b;">'I'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">337</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'J'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">276</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'K'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">476</span>)<span style="color: #abb2bf;">, </span>(<span style="color: #e5c07b;">'L'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">353</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'M'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">888</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'N'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">567</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'O'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">312</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'P'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">795</span>)<span style="color: #abb2bf;">,</span>
(<span style="color: #e5c07b;">'Q'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">467</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'R'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">927</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'S'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">650</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'T'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">574</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'U'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">470</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'V'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">624</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'W'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">747</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'X'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">915</span>)<span style="color: #abb2bf;">,</span>
(<span style="color: #e5c07b;">'Y'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">406</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'Z'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">617</span>)]</span></div><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span><div><span style="font-family: Source Code Pro; font-size: x-small;">讀取來自檔案所建構之 <span style="color: #56b6c2;">tuple</span> of <span style="color: #56b6c2;">list</span> 內容:</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">[(<span style="color: #e5c07b;">'A'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">729</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'B'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">801</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'C'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">588</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'D'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">409</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'E'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">776</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'F'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">393</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'G'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">834</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'H'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">484</span>)<span style="color: #abb2bf;">,</span>
(<span style="color: #e5c07b;">'I'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">337</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'J'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">276</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'K'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">476</span>)<span style="color: #abb2bf;">, </span>(<span style="color: #e5c07b;">'L'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">353</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'M'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">888</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'N'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">567</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'O'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">312</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'P'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">795</span>)<span style="color: #abb2bf;">,</span>
(<span style="color: #e5c07b;">'Q'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">467</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'R'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">927</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'S'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">650</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'T'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">574</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'U'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">470</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'V'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">624</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'W'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">747</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'X'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">915</span>)<span style="color: #abb2bf;">,</span>
(<span style="color: #e5c07b;">'Y'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">406</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'Z'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">617</span>)]</span></div><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span><div><span style="font-family: Source Code Pro; font-size: x-small;">執行時間:<span style="color: #c678dd;">0.003</span> 秒</span></div></div><p><span style="font-size: medium;"><br />test.bin 檔案之16進位檢視:<br /><a href="https://1.bp.blogspot.com/-b0Jzp6fsKg8/X3vcbMeIyqI/AAAAAAAAUcY/frrq6C4GOtgFSGhtQStDal3bkonYfHNKQCLcBGAsYHQ/s706/16.png" style="clear: left; display: inline; margin-bottom: 1em; margin-right: 1em; text-align: center;"><img border="0" data-original-height="124" data-original-width="706" src="https://1.bp.blogspot.com/-b0Jzp6fsKg8/X3vcbMeIyqI/AAAAAAAAUcY/frrq6C4GOtgFSGhtQStDal3bkonYfHNKQCLcBGAsYHQ/s16000/16.png" /></a></span></p><br /><p><br /></p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-57788925981562478482020-10-04T09:20:00.001+08:002020-10-04T09:20:26.469+08:00二進位檔案之16進位檢視器:hexdump for VSCode<p><span style="font-size: medium;">利用 </span><span style="font-family: arial;"><span style="color: #990000; font-size: large;"><a href="https://marketplace.visualstudio.com/items?itemName=slevesque.vscode-hexdump">Hexdump for VSCode Extension</a></span> </span><span style="font-size: medium;">可</span><span style="font-size: large;">邊</span><span style="font-size: large;">寫程式,隨時檢視二進位檔案輸出結果 (以十六進位模式檢視),非常方便。</span></p><p></p><div class="separator" style="clear: both; text-align: center;"><a href="https://marketplace.visualstudio.com/items?itemName=slevesque.vscode-hexdump" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="177" data-original-width="617" src="https://1.bp.blogspot.com/-JLS9oFeFhcE/X3ki6qGjThI/AAAAAAAAUcM/xHbVeO0dpJ8npGXmhlVDK776KqScKxTPACLcBGAsYHQ/s16000/hexdump.jpg" /></a></div><br /><span style="font-size: large;"><br /></span><p></p><p><br /></p>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-67460955609975255462020-09-23T14:17:00.003+08:002020-09-23T14:17:58.237+08:00揮灑Python(68):List of Tuple 基本操作 - 轉換字典、排序<div style="background-color: #282c34; color: #bbbbbb; line-height: 20px; white-space: pre;"><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># -------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># List of Tuple 基本操作</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># -------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># Convert a list of Tuples into Dictionary</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># -------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 使用 dict() 方法</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">a <span style="color: #e06c75;">=</span> [(<span style="color: #e5c07b;">'a'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">3</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'b'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">4</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'c'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">5</span>)]</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">d1 <span style="color: #e06c75;">=</span> {}</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">d1 <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">dict</span>(a)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"d1 內容:"</span><span style="color: #abb2bf;">,</span> d1)</span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># -------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 另一種方法使用 setdefault()</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">d2 <span style="color: #e06c75;">=</span> {}</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">for</span> key<span style="color: #abb2bf;">,</span> value <span style="color: #e06c75;">in</span> a<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> d2<span style="color: #abb2bf;">.</span>setdefault(key<span style="color: #abb2bf;">,</span> value)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"d2 內容:"</span><span style="color: #abb2bf;">,</span> d2)</span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># -------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">total <span style="color: #e06c75;">=</span> <span style="color: #98c379;">sum</span>(d2<span style="color: #abb2bf;">.</span>values())</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"d2 字典中的數值總和為:"</span><span style="color: #abb2bf;">,</span> total)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"---------------------------------"</span>)</span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># -------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"d2 字典中的 items, keys, values :"</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(d2<span style="color: #abb2bf;">.</span>items()<span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">"</span><span style="color: #56b6c2;">\n</span><span style="color: #e5c07b;">"</span><span style="color: #abb2bf;">,</span> d2<span style="color: #abb2bf;">.</span>keys()<span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">"</span><span style="color: #56b6c2;">\n</span><span style="color: #e5c07b;">"</span><span style="color: #abb2bf;">,</span> d2<span style="color: #abb2bf;">.</span>values())</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"---------------------------------"</span>)</span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># -------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">bigThan3 <span style="color: #e06c75;">=</span> {key<span style="color: #abb2bf;">:</span> value <span style="color: #e06c75;">for</span> key<span style="color: #abb2bf;">,</span> value <span style="color: #e06c75;">in</span> d2<span style="color: #abb2bf;">.</span>items() <span style="color: #e06c75;">if</span> value <span style="color: #e06c75;">></span> <span style="color: #c678dd;">3</span>}</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"d2 字典中的值 > 3 者:"</span><span style="color: #abb2bf;">,</span> bigThan3)</span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># -------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># {key: value for key, value in d2.items() if value > 3}</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 這個意思是集成由 key: value 配對組成的字典結構 {}, 當中要符合</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 所有在 d2.items() 裡的 key, value 配對中其 value > 3 者。</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 這裡的 key: value 並非 keyword 關鍵字,使用別的名稱亦可,例如</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># bigThan3 = {k: v for k, v in d2.items() if v > 3}</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># -------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"---------------------------------"</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">box <span style="color: #e06c75;">=</span> [<span style="color: #c678dd;">12</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">24</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">13</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">56</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">84</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">91</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">75</span>]</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"box 原始內容:"</span><span style="color: #abb2bf;">,</span> box)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">box<span style="color: #abb2bf;">.</span>sort()</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"box 經過排序(小->大):"</span><span style="color: #abb2bf;">,</span> box)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">item <span style="color: #e06c75;">=</span> box<span style="color: #abb2bf;">.</span>pop(<span style="color: #e06c75;">-</span><span style="color: #c678dd;">1</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"box pop 出最後一個元素(-1) 結果:"</span><span style="color: #abb2bf;">,</span> box)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"---------------------------------"</span>)</span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># --------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">books <span style="color: #e06c75;">=</span> [(<span style="color: #e5c07b;">"C++"</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">12</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">"Python"</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">25</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">"Java"</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">21</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">"Rust"</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">16</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">"VB"</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">13</span>)]</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"books 原始內容:"</span><span style="color: #abb2bf;">,</span> books)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">books<span style="color: #abb2bf;">.</span>sort(<span style="color: #d19a66; font-style: italic;">key</span><span style="color: #e06c75;">=</span><span style="color: #56b6c2;">lambda</span> <span style="color: #d19a66; font-style: italic;">k</span>: k[<span style="color: #c678dd;">0</span>])</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"依 tuple 之第 1 個元素排序(小->大)"</span><span style="color: #abb2bf;">,</span> books)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">books<span style="color: #abb2bf;">.</span>sort(<span style="color: #d19a66; font-style: italic;">key</span><span style="color: #e06c75;">=</span><span style="color: #56b6c2;">lambda</span> <span style="color: #d19a66; font-style: italic;">k</span>: k[<span style="color: #c678dd;">1</span>]<span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">reverse</span><span style="color: #e06c75;">=</span><span style="color: #56b6c2;">True</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"依 tuple 之第 2 個元素排序(大->小)"</span><span style="color: #abb2bf;">,</span> books)</span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># -------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># pop(-1) => 取出倒數第 1 個元素 => 也就是最後一個;若要取出倒</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 數第 2 個元素呢? => pop(-2),若要取出串列的第 1 個元素呢?</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># => pop(0) , 記得索引註標從 0 開始..</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># sort() 執行完畢後,會直接改變原始串列內容,另一個函數 sorted()</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 則不會。 sort : 預設由小排到大, 可以利用 lambda 表達式來達成依</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 鍵值排序之功能,「key=lambda k: k[0]」 係指依 list 列表中之 </span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># tuple 第 1 個元素(索引0)為鍵值予以排序,若要由大排到小,可以另</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 加參數 reverse=True</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># -------------------------------------------------------</span></span></div><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span><div><span style="font-family: Source Code Pro; font-size: x-small;">執行結果:</span></div><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span><div><span style="font-family: Source Code Pro; font-size: x-small;">d1 內容: {<span style="color: #e5c07b;">'a'</span><span style="color: #abb2bf;">:</span> <span style="color: #c678dd;">3</span><span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">'b'</span><span style="color: #abb2bf;">:</span> <span style="color: #c678dd;">4</span><span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">'c'</span><span style="color: #abb2bf;">:</span> <span style="color: #c678dd;">5</span>}</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">d2 內容: {<span style="color: #e5c07b;">'a'</span><span style="color: #abb2bf;">:</span> <span style="color: #c678dd;">3</span><span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">'b'</span><span style="color: #abb2bf;">:</span> <span style="color: #c678dd;">4</span><span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">'c'</span><span style="color: #abb2bf;">:</span> <span style="color: #c678dd;">5</span>}</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">d2 字典中的數值總和為: <span style="color: #c678dd;">12</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #f8f8f0;">--------------------------------</span><span style="color: #e06c75;">-</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">d2 字典中的 items<span style="color: #abb2bf;">,</span> keys<span style="color: #abb2bf;">,</span> values <span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">dict_items([(<span style="color: #e5c07b;">'a'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">3</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'b'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">4</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'c'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">5</span>)]) </span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> dict_keys([<span style="color: #e5c07b;">'a'</span><span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">'b'</span><span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">'c'</span>]) </span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> dict_values([<span style="color: #c678dd;">3</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">4</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">5</span>])</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #f8f8f0;">--------------------------------</span><span style="color: #e06c75;">-</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">d2 字典中的值 <span style="color: #e06c75;">></span> <span style="color: #c678dd;">3</span> 者: {<span style="color: #e5c07b;">'b'</span><span style="color: #abb2bf;">:</span> <span style="color: #c678dd;">4</span><span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">'c'</span><span style="color: #abb2bf;">:</span> <span style="color: #c678dd;">5</span>}</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #f8f8f0;">--------------------------------</span><span style="color: #e06c75;">-</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">box 原始內容: [<span style="color: #c678dd;">12</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">24</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">13</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">56</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">84</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">91</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">75</span>]</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">box 經過排序(小<span style="color: #f8f8f0;">-></span>大): [<span style="color: #c678dd;">12</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">13</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">24</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">56</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">75</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">84</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">91</span>]</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">box pop 出最後一個元素(<span style="color: #e06c75;">-</span><span style="color: #c678dd;">1</span>) 結果: [<span style="color: #c678dd;">12</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">13</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">24</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">56</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">75</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">84</span>]</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #f8f8f0;">--------------------------------</span><span style="color: #e06c75;">-</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">books 原始內容: [(<span style="color: #e5c07b;">'C++'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">12</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'Python'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">25</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'Java'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">21</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'Rust'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">16</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'VB'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">13</span>)]</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">依 <span style="color: #56b6c2;">tuple</span> 之第 <span style="color: #c678dd;">1</span> 個元素排序(小<span style="color: #f8f8f0;">-></span>大) [(<span style="color: #e5c07b;">'C++'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">12</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'Java'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">21</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'Python'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">25</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'Rust'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">16</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'VB'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">13</span>)]</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">依 <span style="color: #56b6c2;">tuple</span> 之第 <span style="color: #c678dd;">2</span> 個元素排序(大<span style="color: #f8f8f0;">-></span>小) [(<span style="color: #e5c07b;">'Python'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">25</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'Java'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">21</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'Rust'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">16</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'VB'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">13</span>)<span style="color: #abb2bf;">,</span> (<span style="color: #e5c07b;">'C++'</span><span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">12</span>)]</span></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-23155230470443428752020-09-22T16:36:00.004+08:002020-09-25T14:08:17.797+08:00揮灑Python(67):Everything Is an Object, ==, is 的淺釋<div style="background-color: #282c34; color: #bbbbbb; line-height: 20px; white-space: pre;"><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># -------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># Python 開宗明義:Everything Is an Object</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># Python is an object-oriented programming </span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># language, and in Python everything is an object.</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 因此,「None」也是 object,None 是 class 'NoneType',</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># None 是一個空值,但不能理解為空字串;也不是邏輯 False;</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 更不是數值 0,None 的意思是:「什麼都沒有」。然而,當其</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 顯式或隱式被轉換成布林值(boolean)時,其值便為 False</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># -------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">a <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">None</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">b <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">None</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">c <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">False</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">d <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">123</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">e <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">123</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">d <span style="color: #e06c75;">+=</span> <span style="color: #c678dd;">1</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># ------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">if</span> a <span style="color: #e06c75;">==</span> <span style="color: #56b6c2;">None</span><span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"a == None"</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">if</span> a <span style="color: #e06c75;">is</span> <span style="color: #56b6c2;">None</span><span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"a is None"</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">if</span> a <span style="color: #e06c75;">==</span> b<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"a == b"</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">if</span> a <span style="color: #e06c75;">is</span> b<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"a is b"</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">if</span> a <span style="color: #e06c75;">is</span> c<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"a is c"</span>) <span style="color: #676f7d;"># None is False 不成立,沒有輸出</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">if</span> a <span style="color: #e06c75;">==</span> c<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"a == c"</span>) <span style="color: #676f7d;"># None == False 不成立,沒有輸出</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">if</span> d <span style="color: #e06c75;">==</span> e<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"d == e"</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">if</span> d <span style="color: #e06c75;">is</span> e<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"d is e"</span>)</span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># ------------------------------------------------------</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># id:取得物件記憶體的位址,記得 python 視所有對象都是物件,</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 即便是一個數值也是物件。</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># 「==」判斷兩者的值是否相等;「is」判斷兩者是否參考到同一物件</span></span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># ------------------------------------------------------</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"a 的記憶體位址:"</span><span style="color: #abb2bf;">,</span> <span style="color: #98c379;">id</span>(a))</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"b 的記憶體位址:"</span><span style="color: #abb2bf;">,</span> <span style="color: #98c379;">id</span>(b))</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"d 的記憶體位址:"</span><span style="color: #abb2bf;">,</span> <span style="color: #98c379;">id</span>(d))</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"e 的記憶體位址:"</span><span style="color: #abb2bf;">,</span> <span style="color: #98c379;">id</span>(e))</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"None 的記憶體位址:"</span><span style="color: #abb2bf;">,</span> <span style="color: #98c379;">id</span>(<span style="color: #56b6c2;">None</span>))</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"None 的型態:"</span><span style="color: #abb2bf;">,</span> <span style="color: #56b6c2;">type</span>(<span style="color: #56b6c2;">None</span>))</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">e <span style="color: #e06c75;">+=</span> <span style="color: #c678dd;">1</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">if</span> d <span style="color: #e06c75;">==</span> e<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"d == e"</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #e06c75;">if</span> d <span style="color: #e06c75;">is</span> e<span style="color: #abb2bf;">:</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"d is e"</span>)</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"e 的記憶體位址:"</span><span style="color: #abb2bf;">,</span> <span style="color: #98c379;">id</span>(e))</span></div><div><span style="color: #676f7d;"><span style="font-family: Source Code Pro; font-size: x-small;"># -----------------------------------------------------</span></span></div><span style="font-family: Source Code Pro; font-size: x-small;"><br /></span><div><span style="font-family: Source Code Pro; font-size: x-small;">執行結果:</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">a <span style="color: #e06c75;">==</span> <span style="color: #56b6c2;">None</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">a <span style="color: #e06c75;">is</span> <span style="color: #56b6c2;">None</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">a <span style="color: #e06c75;">==</span> b</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">a <span style="color: #e06c75;">is</span> b</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">a 的記憶體位址: <span style="color: #c678dd;">140726332790912</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">b 的記憶體位址: <span style="color: #c678dd;">140726332790912</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">d 的記憶體位址: <span style="color: #c678dd;">140726333023744</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">e 的記憶體位址: <span style="color: #c678dd;">140726333023712</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #56b6c2;">None</span> 的記憶體位址: <span style="color: #c678dd;">140726332790912</span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;"><span style="color: #56b6c2;">None</span> 的型態: <span style="color: #e06c75;"><</span><span style="color: #56b6c2;">class</span> <span style="color: #e5c07b;">'NoneType'</span><span style="color: #e06c75;">></span></span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">d <span style="color: #e06c75;">==</span> e</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">d <span style="color: #e06c75;">is</span> e</span></div><div><span style="font-family: Source Code Pro; font-size: x-small;">e 的記憶體位址: <span style="color: #c678dd;">140726333023744</span></span></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-11573919629436982362020-09-13T20:05:00.003+08:002020-10-04T09:23:50.107+08:00揮灑Python(66):Binary String 二進位0,1字串操作:轉整數、轉bytes並寫入二進位檔案<div style="background-color: #282c34; color: #bbbbbb; font-family: "Source Code Pro", Consolas, "Courier New", monospace; line-height: 20px; white-space: pre;"><div><span style="color: #8d96a5;"><span style="font-size: x-small;"># --------------------------------------------------------------</span></span></div><div><span style="color: #8d96a5;"><span style="font-size: x-small;"># binary string 二進位0,1字串之操作:轉整數、轉bytes並寫入二進位檔案</span></span></div><div><span style="color: #8d96a5;"><span style="font-size: x-small;"># 以下 logo.jpg 可以任意找張圖片,不要太大,最好20~30KB就好,因為有print</span></span></div><div><span style="color: #8d96a5;"><span style="font-size: x-small;"># 輸出,所以較費時..</span></span></div><div><span style="color: #8d96a5;"><span style="font-size: x-small;"># --------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;">byteCnt <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">0</span></span></div><div><span style="font-size: x-small;">srcFilePath <span style="color: #e06c75;">=</span> <span style="color: #e5c07b;">"logo.jpg"</span></span></div><div><span style="font-size: x-small;">destFilePath <span style="color: #e06c75;">=</span> <span style="color: #e5c07b;">"dest.jpg"</span></span></div><div><span style="color: #8d96a5;"><span style="font-size: x-small;"># --------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">with</span> <span style="color: #98c379;">open</span>(srcFilePath<span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">"rb"</span>) <span style="color: #e06c75;">as</span> srcFile<span style="color: #abb2bf;">:</span></span></div><div><span style="font-size: x-small;"> srcData <span style="color: #e06c75;">=</span> srcFile<span style="color: #abb2bf;">.</span>read() </span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># ----------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># 一次讀畢所有檔案內容並轉存 srcData,srcData 是 bytes 串流資料</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># rb : 二進位檔案讀取 / wb : 二進位檔案寫入</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># ----------------------------------------------------------</span></span></div><div><span style="font-size: x-small;">srcFile<span style="color: #abb2bf;">.</span>close()</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;"><span style="color: #e06c75;">with</span> <span style="color: #98c379;">open</span>(destFilePath<span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">"wb"</span>) <span style="color: #e06c75;">as</span> destFile<span style="color: #abb2bf;">:</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> bte <span style="color: #e06c75;">in</span> srcData<span style="color: #abb2bf;">:</span> </span></div><div><span style="font-size: x-small;"> byteCnt <span style="color: #e06c75;">+=</span> <span style="color: #c678dd;">1</span> </span></div><div><span style="font-size: x-small;"> binBits <span style="color: #e06c75;">=</span> <span style="color: #e5c07b;">"</span><span style="color: #56b6c2;">{0:0>8b}</span><span style="color: #e5c07b;">"</span><span style="color: #abb2bf;">.</span>format(bte) </span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># -----------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># bte 是 0-255 的十進位數值 => 利用 format 轉換成 8-bits</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># 的 bit-string (也就是 0101..序列). "{0:0>8b}" 格式化字串</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># 設定為 8 個位數的二進位格式(8b),靠右對齊且不足位者補 0(0>)</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># binBits = "{0:0>8b}".format(bte) => 得8位元的二進位字串</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># -----------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> decimalFormat <span style="color: #e06c75;">=</span> <span style="color: #56b6c2;">int</span>(binBits<span style="color: #abb2bf;">,</span> <span style="color: #c678dd;">2</span>)</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">print</span>(bte<span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">"</span><span style="color: #56b6c2;">\t</span><span style="color: #e5c07b;">"</span><span style="color: #abb2bf;">,</span> binBits<span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">"</span><span style="color: #56b6c2;">\t</span><span style="color: #e5c07b;">"</span><span style="color: #abb2bf;">,</span> decimalFormat)</span></div><div><span style="font-size: x-small;"> destFile<span style="color: #abb2bf;">.</span>write(<span style="color: #56b6c2;">bytes</span>([decimalFormat]))</span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># -----------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># binBits為8位元的二進位字串(ex:10110110),利用 int(x,base)</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># 將原始 x(字串型別)且基底為 base 的字串資料轉換成整數值.</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># decimalFormat = int(binBits, 2) => 轉換成十進位的整數值</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># ex: int("10101100", 2) => 172</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># 最後寫入二進位檔案要以 write bytes 的方式來處理..</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># 先把 decimalFormat 這十進位數值轉換成 byte,可調用 bytes()</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># => bytes([decimalFormat])</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;"># -----------------------------------------------------</span></span></div><div><span style="font-size: x-small;">destFile<span style="color: #abb2bf;">.</span>close() </span></div><div><span style="color: #8d96a5;"><span style="font-size: x-small;">#</span></span></div><div><span style="font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"total byte : "</span><span style="color: #abb2bf;">,</span> byteCnt)</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">執行結果(片段擷取):</span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">255</span> <span style="color: #c678dd;">11111111</span> <span style="color: #c678dd;">255</span></span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">216</span> <span style="color: #c678dd;">11011000</span> <span style="color: #c678dd;">216</span></span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">255</span> <span style="color: #c678dd;">11111111</span> <span style="color: #c678dd;">255</span></span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">224</span> <span style="color: #c678dd;">11100000</span> <span style="color: #c678dd;">224</span></span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">0</span> <span style="color: #c678dd;">00000000</span> <span style="color: #c678dd;">0</span></span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">16</span> <span style="color: #c678dd;">0</span><span style="color: #f8f8f0;">0010000</span> <span style="color: #c678dd;">16</span></span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">74</span> <span style="color: #c678dd;">0</span><span style="color: #f8f8f0;">1001010</span> <span style="color: #c678dd;">74</span></span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">70</span> <span style="color: #c678dd;">0</span><span style="color: #f8f8f0;">1000110</span> <span style="color: #c678dd;">70</span></span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">73</span> <span style="color: #c678dd;">0</span><span style="color: #f8f8f0;">1001001</span> <span style="color: #c678dd;">73</span></span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">70</span> <span style="color: #c678dd;">0</span><span style="color: #f8f8f0;">1000110</span> <span style="color: #c678dd;">70</span></span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">0</span> <span style="color: #c678dd;">00000000</span> <span style="color: #c678dd;">0</span></span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">.........</span>.<span style="color: #abb2bf;">.</span></span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">.........</span>.<span style="color: #abb2bf;">.</span></span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">163</span> <span style="color: #c678dd;">10100011</span> <span style="color: #c678dd;">163</span></span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">73</span> <span style="color: #c678dd;">0</span><span style="color: #f8f8f0;">1001001</span> <span style="color: #c678dd;">73</span></span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">41</span> <span style="color: #c678dd;">0</span><span style="color: #f8f8f0;">0101001</span> <span style="color: #c678dd;">41</span></span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">170</span> <span style="color: #c678dd;">10101010</span> <span style="color: #c678dd;">170</span></span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">159</span> <span style="color: #c678dd;">10011111</span> <span style="color: #c678dd;">159</span></span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">255</span> <span style="color: #c678dd;">11111111</span> <span style="color: #c678dd;">255</span></span></div><div><span style="font-size: x-small;"><span style="color: #c678dd;">217</span> <span style="color: #c678dd;">11011001</span> <span style="color: #c678dd;">217</span></span></div><div><span style="font-size: x-small;">total byte <span style="color: #abb2bf;">:</span> <span style="color: #c678dd;">861</span></span></div><br /></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-36406075611494378722020-09-08T15:47:00.002+08:002020-09-08T16:10:33.388+08:00揮灑Python(65):Binary二進位檔案的讀與寫 - 複製檔案為例<div><div style="background-color: #282c34; color: #bbbbbb; font-family: "source code pro", consolas, "courier new", monospace; line-height: 20px; white-space: pre;"><div><span style="font-size: x-small;"><div style="font-size: medium;"><span style="color: #868b94;"><span style="font-size: x-small;"># -------------------------------------------------</span></span></div><div style="font-size: medium;"><span style="color: #868b94;"><span style="font-size: x-small;"># Binary二進位檔案的讀與寫 - 複製檔案為例</span></span></div><div style="font-size: medium;"><span style="color: #868b94;"><span style="font-size: x-small;"># -------------------------------------------------</span></span></div></span></div><div><span style="font-size: x-small;">byteCnt <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">0</span></span></div><div><span style="font-size: x-small;">srcFilePath <span style="color: #e06c75;">=</span> <span style="color: #e5c07b;">"lotus.jpg"</span></span></div><div><span style="font-size: x-small;">destFilePath <span style="color: #e06c75;">=</span> <span style="color: #e5c07b;">"lotus_copy.jpg"</span></span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># -------------------------------------------------</span></span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># 來源檔 lotus.jpg 複製並寫入目標檔 lotus_copy.jpg</span></span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># -------------------------------------------------</span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">with</span> <span style="color: #98c379;">open</span>(srcFilePath<span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">"rb"</span>) <span style="color: #e06c75;">as</span> srcFile<span style="color: #abb2bf;">:</span></span></div><div><span style="font-size: x-small;"> srcData <span style="color: #e06c75;">=</span> srcFile<span style="color: #abb2bf;">.</span>read() <span style="color: #868b94;"># srcData是bytes串流資料</span></span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># -------------------------------------------------</span></span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">with</span> <span style="color: #98c379;">open</span>(destFilePath<span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">"wb"</span>) <span style="color: #e06c75;">as</span> destFile<span style="color: #abb2bf;">:</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> bte <span style="color: #e06c75;">in</span> srcData<span style="color: #abb2bf;">:</span></span></div><div><span style="font-size: x-small;"> byteCnt <span style="color: #e06c75;">+=</span> <span style="color: #c678dd;">1</span></span></div><div><span style="font-size: x-small;"> <span style="color: #868b94;"># -----------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #868b94;"># print(bte, "=>", hex(bte), end=",")</span></span></div><div><span style="font-size: x-small;"> <span style="color: #868b94;"># bte 為 0~255 的 10 進位數值,hex(bte) =></span></span></div><div><span style="font-size: x-small;"> <span style="color: #868b94;"># 轉 16 進位輸出</span></span></div><div><span style="font-size: x-small;"> <span style="color: #868b94;"># -----------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"</span><span style="color: #56b6c2;">{0:<6}</span><span style="color: #e5c07b;">"</span><span style="color: #abb2bf;">.</span>format(<span style="color: #98c379;">hex</span>(bte))<span style="color: #abb2bf;">,</span> <span style="color: #d19a66; font-style: italic;">end</span><span style="color: #e06c75;">=</span><span style="color: #e5c07b;">""</span>)</span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">if</span> byteCnt <span style="color: #e06c75;">%</span> <span style="color: #c678dd;">16</span> <span style="color: #e06c75;">==</span> <span style="color: #c678dd;">0</span><span style="color: #abb2bf;">:</span></span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">""</span>)</span></div><div><span style="font-size: x-small;"> <span style="color: #868b94;"># -----------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #868b94;"># print("{0:<6}".format(hex(bte)), end="")</span></span></div><div><span style="font-size: x-small;"> <span style="color: #868b94;"># 利用 format() 完成格式化輸出,{0:<6}表示輸出</span></span></div><div><span style="font-size: x-small;"> <span style="color: #868b94;"># 寬度固定為6個字元寬,並且靠左對齊,不足者補空白.</span></span></div><div><span style="font-size: x-small;"> <span style="color: #868b94;"># 若要靠右對齊則「>」,置中對齊為「^」。又 end=""</span></span></div><div><span style="font-size: x-small;"> <span style="color: #868b94;"># 表示 print 指令忽略斷行控制. {0:<6} 中的 0 是</span></span></div><div><span style="font-size: x-small;"> <span style="color: #868b94;"># 指 format()中的參數編號,目前只有一個 hex(bte)</span></span></div><div><span style="font-size: x-small;"> <span style="color: #868b94;"># 參數,所以有沒有 0 都沒有關係. 若有多個參數排列就</span></span></div><div><span style="font-size: x-small;"> <span style="color: #868b94;"># 要小心輸出對應次序..</span></span></div><div><span style="font-size: x-small;"> <span style="color: #868b94;"># -----------------------------------------</span></span></div><div><span style="font-size: x-small;"> destFile<span style="color: #abb2bf;">.</span>write(<span style="color: #56b6c2;">bytes</span>([bte]))</span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># -------------------------------------------------</span></span></div><div><span style="font-size: x-small;"><span style="color: #98c379;">print</span>(<span style="color: #e5c07b;">"</span><span style="color: #56b6c2;">\n</span><span style="color: #e5c07b;">總共有: "</span><span style="color: #abb2bf;">,</span> byteCnt<span style="color: #abb2bf;">,</span> <span style="color: #e5c07b;">" Bytes"</span>)</span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># -------------------------------------------------------------</span></span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># 字串格式化輸出可參考:</span></span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># https://blog.jaycetyle.com/2018/01/python-format-string/</span></span></div><div><span style="color: #868b94;"><span style="font-size: x-small;">#</span></span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># open() 裡頭的參數,"rb" => 二進位模式讀取 "wb" => 二進位模式寫入</span></span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># bytes 是 Python3 內建資料型別,可以調用 bytes() 將範圍0~255之整數值</span></span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># 轉換為二進位的 byte 資料,特別注意的是:使用 bytes() 進行轉換時,整數</span></span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># 資料一定要放在 [] 之中,例如以下示例:</span></span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># print(bytes([3])) => b'\x03'</span></span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># print(bytes(3)) => b'\x00\x00\x00' => 因為漏掉 []</span></span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># print(bytes([12, 3, 128])) => b'\x0c\x03\x80'</span></span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># -------------------------------------------------------------</span></span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># 處理二進位檔案進行寫入動作時,就是利用 destFile.write(bytes([bte]))</span></span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># 的方式寫入,切記不要漏掉 [] 。</span></span></div><div><span style="color: #868b94;"><span style="font-size: x-small;"># -------------------------------------------------------------</span></span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">輸出結果(片段):</span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">ff</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">d8</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">ff</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">e0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">10</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">4a</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">46</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">49</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">46</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">1</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">1</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">1</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">48</span> </span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">48</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">ff</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">e1</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">e6</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">45</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">78</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">69</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">66</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">49</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">49</span> </span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">2a</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">8</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">5</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">12</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">1</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">3</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">1</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> </span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">1</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">1</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">1c</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">4a</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> </span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">32</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">1</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">2</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">14</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">66</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">13</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">2</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">3</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> </span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">1</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">1</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">69</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">87</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">4</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">1</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> <span style="color: #56b6c2;">0x</span><span style="color: #c678dd;">0</span> </span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">...</span>.<span style="color: #abb2bf;">.</span></span></div><div><span style="font-size: x-small;"><span style="color: #56b6c2;">...</span>.<span style="color: #abb2bf;">.</span></span></div></div></div><div><span style="font-size: x-small;"><br /></span></div><div>輸出結果對比一下利用 WinHex 對 lotus.jpg 檔案以16進位模式檢視之截圖 (觀察前幾個 bytes即可)<br /><br /></div><div class="separator" style="clear: both; text-align: center;"><a href="https://1.bp.blogspot.com/-Zltk467W9Vw/X1c2ty9AfvI/AAAAAAAAUSs/UW_PCbhTGAM7tIzrDhQebIXV4jG8EXoVgCLcBGAsYHQ/s654/lotus_hex.png" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" data-original-height="155" data-original-width="654" src="https://1.bp.blogspot.com/-Zltk467W9Vw/X1c2ty9AfvI/AAAAAAAAUSs/UW_PCbhTGAM7tIzrDhQebIXV4jG8EXoVgCLcBGAsYHQ/s16000/lotus_hex.png" /></a></div><br /><div><br /></div><div><br /></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-47302619979454802172020-09-06T17:25:00.004+08:002020-09-06T17:25:32.433+08:00Rust 23事(23):淺談並發(Concurrency) - 執行緒(Thread)<div style="background-color: #282c34; color: #bbbbbb; font-family: "Source Code Pro", Consolas, "Courier New", monospace; line-height: 20px; white-space: pre;"><div><span style="font-size: x-small;"><span style="color: #e06c75;">use</span> std<span style="color: #e06c75;">::</span>thread; </span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">use</span> std<span style="color: #e06c75;">::</span>time<span style="color: #e06c75;">::</span>Duration; </span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">fn</span> <span style="color: #98c379;">main</span>() {</span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">//</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">let</span> someMilliSec <span style="color: #e06c75;">=</span> Duration<span style="color: #e06c75;">::</span><span style="color: #98c379;">from_millis</span>(<span style="color: #c678dd;">3</span>); <span style="color: #8d96a5;">// 設定持續時間=3毫秒</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">let</span> threadA <span style="color: #e06c75;">=</span> thread<span style="color: #e06c75;">::</span><span style="color: #98c379;">spawn</span>(<span style="color: #e06c75;">move</span> <span style="color: #e06c75;">||</span> { </span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> i <span style="color: #e06c75;">in</span> <span style="color: #c678dd;">1</span>..<span style="color: #e06c75;">=</span><span style="color: #c678dd;">8</span> { </span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">println!</span>(<span style="color: #e5c07b;">"hi:{} from A"</span>, i); </span></div><div><span style="font-size: x-small;"> thread<span style="color: #e06c75;">::</span><span style="color: #98c379;">sleep</span>(someMilliSec); <span style="color: #8d96a5;">// 執行緒休眠3毫秒</span></span></div><div><span style="font-size: x-small;"> } </span></div><div><span style="font-size: x-small;"> });</span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// ---------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">let</span> threadB <span style="color: #e06c75;">=</span> thread<span style="color: #e06c75;">::</span><span style="color: #98c379;">spawn</span>(<span style="color: #e06c75;">move</span> <span style="color: #e06c75;">||</span> { </span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> j <span style="color: #e06c75;">in</span> <span style="color: #c678dd;">1</span>..<span style="color: #e06c75;">=</span><span style="color: #c678dd;">8</span> { </span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">println!</span>(<span style="color: #e5c07b;">"hi:{} from B"</span>, j); </span></div><div><span style="font-size: x-small;"> thread<span style="color: #e06c75;">::</span><span style="color: #98c379;">sleep</span>(someMilliSec); <span style="color: #8d96a5;">// 執行緒休眠3毫秒</span></span></div><div><span style="font-size: x-small;"> } </span></div><div><span style="font-size: x-small;"> }); </span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// ---------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// threadA、threadB 為子執行緒,利用 thread::spawn 搭配閉包產生新執行緒,</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 又因為主程式的變數 someMilliSec 無法借用給子執行緒中的閉包使用,因此可透</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 過閉包前方加關鍵字 move 來達到閉包於其 scope 對變數 someMilliSec 嘗試</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 作複製(copy)或移動(move)..</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 透過 let threadA = thread::spawn... 令 threadA 取得 JoinHandle</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 結構實體,之後再利用此結構實體調用 join() 函數來避免因為主執行緒(main </span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// thread) 先結束後導致子執行緒被迫停止. => threadA.join() , 也就是說調用</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// join() 後,即便主執行緒結束了,程式必然會等待其他子執行緒(child thread)</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 全部結束後再結束整個程式。</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// ---------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">for</span> k <span style="color: #e06c75;">in</span> <span style="color: #c678dd;">1</span>..<span style="color: #e06c75;">=</span><span style="color: #c678dd;">5</span> { </span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">println!</span>(<span style="color: #e5c07b;">"hi:{} from main"</span>, k); </span></div><div><span style="font-size: x-small;"> thread<span style="color: #e06c75;">::</span><span style="color: #98c379;">sleep</span>(someMilliSec); <span style="color: #8d96a5;">// 執行緒休眠3毫秒</span></span></div><div><span style="font-size: x-small;"> } </span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// </span></span></div><div><span style="font-size: x-small;"> threadA.<span style="color: #98c379;">join</span>().<span style="color: #98c379;">unwrap</span>(); </span></div><div><span style="font-size: x-small;"> threadB.<span style="color: #98c379;">join</span>().<span style="color: #98c379;">expect</span>(<span style="color: #e5c07b;">"join failed"</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// ---------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// threadA 及 threadB 之 while 迴圈均執行 8 次,但主執行緒之 while 才執</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 行 5 次,又執行緒 sleep 時間均為 3 毫秒,論理,主執行緒會先結束,為避免主</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 執行緒結束後,threadA 及 threadB 被迫執行到一半而終止,因此調用 join()</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// ※※※※※ 本範例每一次執行出來的結果不一定會相同 ※※※※※</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// ---------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 這裡的 unwrap() 其實是個偷懶的方式,號稱「隱式的 panic!」,也就是讓程式</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 設計師輕鬆地迴避撰寫複雜的例外處理(正規的例外處理通常利用 match 模式匹配加</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 上分支判斷),換言之,直接調用 unwrap() 就是當程式發生例外時,採用系統預設</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 的例外處理方式丟出 panic!,但這樣的風險在於當程式執行該片段且發生例外時,</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 這個致命的 panic! 通常會導致整個程式 Crash 掉 ! 然而若非定要嚴謹的實作,</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 如此簡單調用 unwrap() 倒也省心不少..反正就是把例外狀況直接交給系統便是.</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// ---------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 進一步說明:threadA.join() 回傳一個 Result 結構體,其函數原型定義如下:</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// pub fn join(mut self) -> Result<T></span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 如果 Result 的值是 Ok,unwrap() 回傳 Ok 中的值,但若 Result 是 Err,</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// unwrap() 則調用預設(內建)的 panic! </span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 另一種方式則是使用 expect(),並自訂參數傳遞內容來取代原來 unwrap() 觸發</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// panic! 所引發的預設錯誤訊息.. 例如:</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// threadB.join().expect("join failed") 若 panic! => "join failed"</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// ---------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">執行結果:</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">1</span> from main</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">1</span> from A</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">1</span> from B</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">2</span> from B</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">2</span> from main</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">2</span> from A</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">3</span> from A</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">3</span> from main</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">3</span> from B</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">4</span> from A</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">4</span> from main</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">4</span> from B</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">5</span> from main</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">5</span> from A</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">5</span> from B</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">6</span> from A</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">7</span> from A</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">6</span> from B</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">8</span> from A</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">7</span> from B</span></div><div><span style="font-size: x-small;">hi:<span style="color: #c678dd;">8</span> from B</span></div></div>Unknownnoreply@blogger.com0tag:blogger.com,1999:blog-4924322257988972731.post-25165761933513862932020-09-05T00:02:00.003+08:002020-09-05T00:03:50.867+08:00Rust 23事(22):再談談 Closure (閉包)<div style="background-color: #282c34; color: #bbbbbb; font-family: "source code pro", consolas, "courier new", monospace; line-height: 20px; white-space: pre;"><div><span style="font-size: x-small;"><span style="color: #e06c75;">fn</span> <span style="color: #98c379;">main</span>() {</span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">//</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">let</span> helloClosure <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">|</span> <span style="color: #e06c75;">|</span> <span style="color: #e5c07b;">"閉包,你好~"</span>;</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">println!</span>(<span style="color: #e5c07b;">"以下為最簡單的閉包(Closure):"</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">println!</span>(<span style="color: #e5c07b;">"let helloClosure = | | </span><span style="color: #56b6c2;">\"</span><span style="color: #e5c07b;">閉包,你好~</span><span style="color: #56b6c2;">\"</span><span style="color: #e5c07b;">;"</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">println!</span>(<span style="color: #e5c07b;">"調用 helloClosure => {}"</span>, <span style="color: #98c379;">helloClosure</span>());</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">println!</span>(<span style="color: #e5c07b;">"-------------------------------------"</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// -------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 閉包 helloClosure 回傳值為 "閉包,你好~" 字串,也可以表達成:</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// { "閉包,你好~" }; 或 { return "閉包,你好~"; };</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// -------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 閉包可以當成是一種函數物件(function object) 或類似匿名函數的概念,</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// Rust中,閉包的參數與回傳值型別可藉由型別自動推斷取得,因此不須特別敘明..</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// -------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">let</span> closureTest <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">|</span> <span style="color: #e06c75;">mut</span> x <span style="color: #e06c75;">|</span> <span style="color: #e06c75;">-></span> <span style="color: #56b6c2;">i32</span> { <span style="color: #8d96a5;">// x 會被改變 => mut</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">while</span> x <span style="color: #e06c75;"><</span> <span style="color: #c678dd;">10</span> {</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">println!</span>(<span style="color: #e5c07b;">"{}"</span>, x);</span></div><div><span style="font-size: x-small;"> x <span style="color: #e06c75;">+=</span> <span style="color: #c678dd;">1</span>;</span></div><div><span style="font-size: x-small;"> } </span></div><div><span style="font-size: x-small;"> x <span style="color: #8d96a5;">// 相當於 return x; => 閉包可以有回傳值, 本例為 i32</span></span></div><div><span style="font-size: x-small;"> }; </span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// -------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// closureTest 閉包中的敘述可以用 { } 括弧括起來,右括弧之結尾要記得加上</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 「;」,又本例回傳值為 x, 其型別為 i32。回傳值 x 可以表達成 return x;</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 就 Rust 語意而言,回傳值直接標上該變數即可(此時不用加 return 且無需敘</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 述結尾符號「;」),但若以傳統 C/C++ 風格 => return x; </span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// -------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #e06c75;">let</span> c1 <span style="color: #e06c75;">=</span> <span style="color: #98c379;">closureTest</span>(<span style="color: #c678dd;">3</span>); </span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">println!</span>(<span style="color: #e5c07b;">"c1 = {}"</span>, c1);</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">println!</span>(<span style="color: #e5c07b;">"-------------------------------------"</span>);</span></div><div><span style="font-size: x-small;"> <span style="color: #98c379;">println!</span>(<span style="color: #e5c07b;">"closureTest(7)執行後回傳值 = {}"</span>, <span style="color: #98c379;">closureTest</span>(<span style="color: #c678dd;">7</span>)) </span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// -------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// let c1 = closureTest(3) => 利用 c1 接收 closureTest(3) 回傳值,</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// 參數傳遞:3 -> mut x ,又閉包本體為一個 while 迴圈,且最終回傳值為 x</span></span></div><div><span style="font-size: x-small;"> <span style="color: #8d96a5;">// -------------------------------------------------------------</span></span></div><div><span style="font-size: x-small;">}</span></div><span style="font-size: x-small;"><br /></span><div><span style="font-size: x-small;">執行結果:</span></div><div><span style="font-size: x-small;">以下為最簡單的閉包(Closure):</span></div><div><span style="font-size: x-small;"><span style="color: #e06c75;">let</span> helloClosure <span style="color: #e06c75;">=</span> <span style="color: #e06c75;">|</span> <span style="color: #e06c75;">|</span> <span style="color: #e5c07b;">"閉包,你好~"</span>;</span></div><div><span style="font-size: x-small;">調用 helloClosure <span style="color: #e06c75;">=></span> 閉包,你好~</span></div><div><span style="color: #e06c75;"><span style="font-size: x-small;">-------------------------------------</span></span></div><div><span style="color: #c678dd;"><span style="font-size: x-small;">3</span></span></div><div><span style="color: #c678dd;"><span style="font-size: x-small;">4</span></span></div><div><span style="color: #c678dd;"><span style="font-size: x-small;">5</span></span></div><div><span style="color: #c678dd;"><span style="font-size: x-small;">6</span></span></div><div><span style="color: #c678dd;"><span style="font-size: x-small;">7</span></span></div><div><span style="color: #c678dd;"><span style="font-size: x-small;">8</span></span></div><div><span style="color: #c678dd;"><span style="font-size: x-small;">9</span></span></div><div><span style="font-size: x-small;">c1 <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">10</span></span></div><div><span style="color: #e06c75;"><span style="font-size: x-small;">-------------------------------------</span></span></div><div><span style="color: #c678dd;"><span style="font-size: x-small;">7</span></span></div><div><span style="color: #c678dd;"><span style="font-size: x-small;">8</span></span></div><div><span style="color: #c678dd;"><span style="font-size: x-small;">9</span></span></div><div><span style="font-size: x-small;"><span style="color: #98c379;">closureTest</span>(<span style="color: #c678dd;">7</span>)執行後回傳值 <span style="color: #e06c75;">=</span> <span style="color: #c678dd;">10</span></span></div></div>Unknownnoreply@blogger.com0