作者poyenc (发箍)
看板C_and_CPP
标题Re: [问题] 请问我这个程式能用回圈做吗?
时间Fri Apr 3 17:01:08 2020
※ 引述《IOP14759 (iop14759)》之铭言:
原文恕删
C++ Community 有一个文化就是:
尽可能地使用现有工具, 如果没现成的就自己
造工具出来
注意上面这句话讲的是自己造工具, 不是自己造程式. 通常在开发
C++ 程式时在做的就是
把手中的工具兜成想要的样子, STL 就是在
这文化薰陶下诞生的产物, 这个概念有点像是玩
接水管的游戏
(後
面会知道原因)
虽然原文在问能不能用回圈做, 但我更想反问原 PO:
为什麽要用回
圈做? 因为
C++ 很少在写回圈的. 这并不是什麽用递回取代回圈的
论述, 而是
写回圈这件事本身就是重工. 而且直接用回圈实作可能
会让你丧失分析问题的能力, 可以参考
Sean Parent 的分享:
GoingNative 2013: C++ Seasoning
https://channel9.msdn.com/Events/GoingNative/2013/Cpp-Seasoning
了解自己想做什麽事情, 才会知道要用什麽工具来达成目的. 原本
的问题可以拆解成几个步骤:
1. 把整数
转换为数个 bit
2. 把这些 bit
转换为对应的 '1' 或 '0' 字元
3. 保留
特定数量的字元储存/输出
以上每个步骤都可以用标准函式库现有的工具来实作, 这个在原文
下方小弟有提供简单的范例. 主要概念是用
std::bitset 取得每个
位元, 用
std::string 储存转换好的字元, 再用
std::string_view 来显示子字串:
范例 #1:
https://wandbox.org/permlink/EX9D7pHtAtIjpPEU
在 C++ 里需要注意物件的生命周期, 具有 value semantic 的型别
如
std::string 在操作时很像 primitive type, 所以很容易就会
创造许多不必要的临时物件拖垮效能, 如此失去写 C++ 的好处. 有
兴趣探讨的话可以参考
Herb Sutter 的
Exceptional C++ 系列书.
范例 #1 虽然简单; 但因为有 raw loop, 本质上还存在以下问题:
1. 转换逻辑和回圈步进方向绑死
2. 高度相依於来源/目的容器型别及操作 (
operator[],
size())
3. 需要储存中间的结果, 最後却不会再用到
为了移除相依性, 我们需要
导入迭代器 (iterator) 的观念, 多了
这个抽象层, 我们可以用以下叙述来印出
std::bitset 的每个位元:
std::bitset<
4> bits(
10);
// print "0101"
std::copy(begin(bits), end(bits),
std::ostream_iterator<
bool>(std::cout,
""));
不过很可惜
std::bitset 并没有提供迭代器介面, 如果要沿用的话
我们必须手刻一个 adaptor 出来, 长相会是下面的样子:
Iterator adaptor for random access range which has not
provided iterator interfaces (C++17)
https://bit.ly/2UDfKfN
我们需要偏特化
std::iterator_traits 才能和 STL Algorithm 无
缝套接, 而且因为要反向寻访位元, 这个迭代器必须符合
LegacyBidirectionalIterator 概念
(concept). 做转换的工作可
以附加在迭代器之上完成, 因为
Boost 里已经有现成的直接套用即
可. 新的范例如下:
范例 #2:
https://wandbox.org/permlink/LxQvdJOm12U9e44l
不同於范例 #1, 104 ~ 107 行等同於
接水管的动作, 得利於模板
(
template) 的特性, 我们在设计水管的时候只需要尽可能地减少对
型别的依赖
(constraint), 就可以最大化复用性. 这个概念将在
C++20 後 Ranges library 趋於完整而逐步出现在其他函式库实作
里, 有兴趣的话可以参考
Eric Niebler 的分享:
CppCon 2015: Ranges for the Standard Library
https://www.youtube.com/watch?v=mFUXNMfaciE
到这篇文的最後, 因为原 PO 的需求是要用
AnsiString 显示部分
位元, 可以想想如何使用上面提到的工具兜出需要的功能? 另外,
如果问题改成: 将二进位表示法字串转成整数. 你的程式码又需要
做什麽修改呢?
--
P1389R0: Guidelines for Teaching C++ to Beginners
https://bit.ly/2GvDWKb
SG20 Education and Recommended Videos for Teaching C++
https://www.cjdb.com.au/sg20-and-videos
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 123.193.76.216 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1585904477.A.3C5.html
※ 编辑: poyenc (123.193.76.216 台湾), 04/03/2020 20:12:09
1F:推 s4300026: 赞 04/05 11:08
2F:推 sarafciel: 推 04/06 00:55
3F:→ flysonics: 推 04/06 18:58