关于c++:C模板元编程实战读书笔记

C++模板元编程是函数式编程,是无副作用的函数(输出雷同,屡次调用输入雷同)。constexpr就是标注这个函数无副作用(数值元函数),与之对应的是类型元函数。类型元函数:输出参数为类型,输入参数也为类型。template <>struct Fun<int>{ using reference_type = int&; using value_type = int;};输出为int,输入为Fun<int>::reference_type/value_type 当constexpr函数传入constexpr参数时,则进行编译期计算,否则进行运行时计算。元数据分为 数值类型模板容器模板:通过可变参数模板作为元数据的容器,另外只在必要时才进行定义。程序、条件分支、循环语句 程序条件分支 std::conditional_t偏特化(留神未齐全特化的类中不容许有齐全特化)std::enable_if_t 当条件为真时返回type,利用了SFINAE,匹配失败并非谬误循环:应用递归运算循环,偏特化作为完结的条件。编译器分支和运行时函数相结合,通过元函数在编译期抉择正确的运行时函数。利用if constexpr抉择运行时执行的代码。CRTP

October 3, 2022 · 1 min · jiezi

关于c++:Folly库代码赏析5FuturePromise模型

前言通常来说,有两种异步模式,一种是基于goroutine的用户态协程并发模型,另一种是基于Future/Promise的并发模型。后者可能将多个Future串联,改善回调天堂这一状况。其实Javascript早就提供了Promise模型,异步基于事件循环来做,每次都是将异步事件插入工夫序列期待下一次调用。而像C++/Rust这些语言就必须通过额定的executor库就安顿异步事件的执行。Rust中曾经有了十分优良的异步运行时tokio,Folly的实现该当是差不多的。 对Folly的介绍基于自底向上进行的办法,从底层building block到下层高级原语。 CoreKeepAlive and DeferredKeepAlive是对executor的平安援用,保障不会在KeepAlive存活时析构executor。 Deferred是尚未设置理论executor的代理,后续须要注入指定的executor。 Info flowCore保护三种info flow producer => consumer:result、callback、executor、priorityconsumer => producer:interrupt 、interrupt handler 相似于Linux中的信号,用于勾销或xxcallback的执行lifetime control: 2 ref counts(attached_ 和 callbackref_),管制析构上面是一张 producer => consumer 的状态转换图,清晰地转换Core的各种状态以及触发条件。 /// +----------------------------------------------------------------+/// | ---> OnlyResult ----- |/// | / \ |/// | (setResult()) (setCallback()) |/// | / \ |/// | Start ---------> ------> Done |/// | \ \ / |/// | \ (setCallback()) (setResult()) |/// | \ \ / |/// | \ ---> OnlyCallback --- |/// | \ or OnlyCallbackAllowInline |/// | \ \ |/// | (setProxy()) (setProxy()) |/// | \ \ |/// | \ ------> Empty |/// | \ / |/// | \ (setCallback()) |/// | \ / |/// | --------> Proxy ---------- |/// +----------------------------------------------------------------+模块设计Core分为CoreBase 和Core<T>,将与模板无关的信息集中在Core<T>中。 ...

October 2, 2022 · 1 min · jiezi

关于c++:Folly库代码赏析4BenchMark

BenchMark框架基于这样一种思维:测量时候肯定有噪声的存在,导致咱们的测量值偏大。因而不应该对多组测量后果求均匀,而是应该求最小值。 第一个乏味的中央是如何确保一个无用的表达式求值,Folly中是利用了句号表达式 + 匿名变量#define BENCHMARK_IMPL(funName, stringName, rv, paramType, paramName) \ static void funName(paramType); \ FOLLY_MAYBE_UNUSED static bool FB_ANONYMOUS_VARIABLE(follyBenchmarkUnused) = \ (::folly::addBenchmark( \ __FILE__, \ stringName, \ [](paramType paramName) -> unsigned { \ funName(paramName); \ return rv; \ }), \ true); \ static void funName(paramType paramName)宏开展之后,就实现了函数的申明和并将测试函数注入框架。 第二个有意思的中央是如何保障一个变量的申明周期在整个代码块内,即咱们心愿BENCHMARK_SUSPEND { v.reserve(n);}BENCHMARK_SUSPEND是通过管制对应变量的生命周期管制计时流程的,因而,咱们心愿在这个宏中结构的变量的生命周期贯通整个代码块。 #define BENCHMARK_SUSPEND \ if (auto FB_ANONYMOUS_VARIABLE(BENCHMARK_SUSPEND) = \ ::folly::BenchmarkSuspender()) { \ } else十分奇妙的利用了在if中申明的变量的scope在else之后完结的冷常识 ref:

October 1, 2022 · 1 min · jiezi

关于c++:排序算法

源码地址(gitee)堆排序源码地址:https://gitee.com/BJFyfwl/Lin...其余排序办法源码地址:https://gitee.com/BJFyfwl/Lin...常见排序算法插入排序: 间接插入排序希尔排序抉择排序: 间接抉择排序堆排序替换排序: 冒泡排序疾速排序归并排序间接插入排序核心思想:将一个数插入一段有序区间。希尔排序核心思想: 先分组预排序(应用间接插入排序),使整个数组靠近有序(小的数在前,大的数在后)再间接插入排序能够将较大的数疾速地挪动到前面,实用于大量数据gap == 1就相当于间接插入排序。gap越大,预排越快,预排序越不靠近有序。gap越小,预排越慢,预排序越靠近有序。间接抉择排序遍历数组,选出最大的数,与最初一个数替换。而后顺次遍历抉择次大的数,与倒数第二个数替换。如此循环。堆排序建堆工夫是O(N)排序工夫是O(logN)堆只存在两种类型:大根堆和小根堆。大根堆:根节点是最大的(即孩子节点 < 父亲节点)小根对:根节点是最小的(即孩子节点 > 父亲节点)堆在逻辑构造上是齐全二叉树,在物理构造上还是数组模式。所以实现堆时,依然以数组来存储。堆的下标法则设父节点下标为 x,右边子节点下标为 y,左边节点下标为 z。y = x*2 + 1;z = x*2 + 2;x = (x - 1)/ 2 或者 (y-1)/ 2;堆排序问题一:假如数组数据很大(有10亿个数,大略4G内存),他们存在文件中,取最大的前k个数解决办法:建设一个 k 个数的小根堆,而后将文件中的数顺次取出与根节点比拟,如果比根节点大,则替换根节点,而后向下调整,如此循环,最初这个小根堆中的数据就是最大的前k个数。堆排序问题二:堆排序:将一个数组升序排列解决办法:将数组建设小根堆,顺次取根节点的数据,而后将根节点数据与开端数据交换,再删除开端数据(即删除最小的那个数了),而后再向下调整,如此循环即可。疾速排序工夫复杂度 O(N * logN)空间复杂度O(logN)稳定性:不稳固如何取要害数key先取数组的第一个数、最初一个数和两头地位的数,而后取这三个数中不是最大也不是最小的那个数作为key。这种办法能够防止key间接选到最大值或者最小值。左右指针法快排 一前一后两个指针,抉择一个要害数key(个别是结尾位或者末位)如果抉择结尾位为要害数key,则让end向后先走,寻找比key小的数,找到小的数后停下。而后pre向前走,寻找比key大的数,找到后进行。而后替换pre的值和end的值,替换完后,end持续向后挪动。始终循环,直到pre和end相遇为止,相遇时的值肯定是比key小的,所以替换key和pre的值这样,key的数就会被挪动到整个数组的两头值地位,它右边的都比它小,左边的都比它大最初应用递归。挖坑法快排 另外定义一个变量sum,用来保留第一个pre,pre的地位则空进去了。而后end先向前挪动,寻找比sum小的数,找到后将end与pre替换,当初end的地位为空。而后pre向前挪动,寻找比sum大的数,找到将pre与end替换,当初pre的地位为空。而后再是end向前挪动………………这样循环直到pre和end相遇为止,相遇时的地位为空,再将sum的值放到相遇的地位上。这样这个数的右边都是比它小的数,左边都是比它大的数。最初应用递归即可。前后指针法快排 起始地位,pre在第一位,end在第二位。而后end向后挪动,寻找比key小的值,找到后,pre++,而后替换pre和end的值。而后持续end向后挪动,直到end拜访完为止最初在替换pre和key的值这样key这个数的右边都是比它小的数,左边都是比它大的数。最初递归即可。递归式快排的小区间优化当数据量很大时,在最初几层递归时,会呈现大量递归(呈现大量递归时可能会栈溢出),然而每个递归解决的数据较小。所以为了防止最初几层的递归,在数据量较小时,间接应用插入排序这样大数据处理的最初几层递归,则变为插入排序,能够缩小大量递归,升高解决工夫。非递归快排应用循环代替递归。为了防止栈溢出,本人创立一个栈(malloc创立的空间是在堆中的),应用循环来进行排序,其实质是本人模仿栈的出栈和压栈。而后将单趟排序隔离进去,压栈时将pre和end的下标压栈,出栈将pre和end传给单趟排序,并且将栈中的pre和end打消,循环如此即可排序。计数排序外围思路:依据所给数组的最大值与小值,开拓等大小的数组,并且初始化为0,遍历数组,将该整数对应下标的新数组的地位加1。(相当于一种映射)例如:给定一个数组 {5,6,7,8,9,6}最大值为9,最小值为5,开拓新数组 arr 大小为 5。遍历数组,第一个数为 5 ,对应下标为 0,即arr[0]++,如此遍历残缺个数组即可。适用范围只适宜数据范畴比拟集中的数组,如果数据集中效率还是很高的。并且只适宜整数,浮点数和字符串等都不适宜。归并排序核心思想:将数组切分成两份,如果右边有序,左边也有序,那么两份归并,整个数组都是有序的了。归并的海量数据处理(外排序)例如:一个4G的文件,文件中是一些整数,将这些整数排序,零碎提供内存为512M 将文件分成 8 等分,而后别离将小文件的数据读取到内存中进行排序(不要用归并,因为归并有O(N)的空间复杂度)这样 8 份小文件中的数据都是有序的了。而后再将 8 分小文件两两进行归并,合称 4 份有序文件而后再归并,最初归并成一个有序的大文件。算法复杂度及稳定性数组中雷同的值,排完序后绝对地位不变,就是稳固的,否则就是不稳固。

September 30, 2022 · 1 min · jiezi

关于c++:Folly库代码赏析3AtomicUnorderedMap

AtomicUnorderedMap是一个不反对删除、反对高并发读写、反对自定义K、V的哈希表,只反对一个findOrConstruct操作。 template <typename Func> std::pair<const_iterator, bool> findOrConstruct(const Key& key, Func&& func) { // 依据哈希算法定位到索引 auto const slot = keyToSlotIdx(key); auto prev = slots_[slot].headAndState_.load(std::memory_order_acquire); // 遍历动态链表查找键是否存在 auto existing = find(key, slot); if (existing != 0) { return std::make_pair(ConstIterator(*this, existing), false); } // 在左近找一个空slot,同时设标记位为CONSTRUCTING auto idx = allocateNear(slot); new (&slots_[idx].keyValue().first) Key(key); func(static_cast<void*>(&slots_[idx].keyValue().second)); while (true) { slots_[idx].next_ = prev >> 2; // we can merge the head update and the CONSTRUCTING -> LINKED update // into a single CAS if slot == idx (which should happen often) auto after = idx << 2; // 第一次就查找到空slot if (slot == idx) { after += LINKED; } else { after += (prev & 3); } // 没有其他人读写原始slot prev if (slots_[slot].headAndState_.compare_exchange_strong(prev, after)) { // success if (idx != slot) { slots_[idx].stateUpdate(CONSTRUCTING, LINKED); } return std::make_pair(ConstIterator(*this, idx), true); } // compare_exchange_strong updates its first arg on failure, so // there is no need to reread prev // 原来的slot有变动,看看是不是其余线程进行了插入 existing = find(key, slot); if (existing != 0) { // our allocated key and value are no longer needed slots_[idx].keyValue().first.~Key(); slots_[idx].keyValue().second.~Value(); slots_[idx].stateUpdate(CONSTRUCTING, EMPTY); return std::make_pair(ConstIterator(*this, existing), false); } } }

September 30, 2022 · 1 min · jiezi

关于c++:Folly库代码赏析1AtomicHashArray

Folly是facebook公司提供的开源C++代码库,品质很高,用以补充规范库和boost库的有余,在性能方面提出了很高的要求。 AtomicHashArray是用于构建AtomicHashMap的原料,在某些条件下面做了额定要求,通过升高通用性达到进步特定条件下性能的目标。 当通过AtomicHashArray::Config构建时,因为static initialization order fiasco,咱们只能通过提供默认函数参数而不是提供一个动态全局实例。 实质上,AtomicHashArray就是一个动态数组,通过CAS操作实现并发插入、删除操作。关键在于如何封装使得对元素操作原子化。 提供了三个标记元素 empty_key、locked_key、erased_key。 插入时:通过原子性的变更key,例如讲empty_key变更为locked_key,从而实现单个元素的上锁,而后再进行value的结构,最初set new_key。当然,这里对key的限度比拟大,要求key可能convert to int32。 删除时:定位到给定元素,而后CAS更改为erased_key即可实现删除操作,只是打了一个墓碑标记,不适宜删除很多元素时应用。 同样的,哈希抵触基于凋谢地址法解决。通过模板提供了线性探测和平方探测两种策略。 迭代器遍历元素时也要越过相应的墓碑和空位。

September 30, 2022 · 1 min · jiezi

关于c++:Folly库代码赏析2AtomicHashMap

AtomicHashArray中通过将key强制转型为std::atomic<KeyT>*来实现key的原子操作。为了防止低廉操作,如通过stringpiece查找string,AtomicHashMap提供了转换函数容许提供可转换位key的查问参数,即便不是同一类型,也能够比拟二者是否相等。AtomicHashMap的插入操作: 向primary AtomicHashArray中插入如果已满,调配sub map并插入底层调配策略: // if subMap == 0 (primary map) =>// bit(s) value// 31 0// 0-30 submap offset (index_ret input)//// if subMap > 0 (secondary maps) =>// bit(s) value// 31 1// 27-30 which subMap// 0-26 subMap offset (index_ret input)底层调配是1个primary map + N个sub map。 总和容量实际上是和2个primary map统一的,为了防止内存节约,通过溢出时再调配多个sub map去防止不必要的内存节约。

September 30, 2022 · 1 min · jiezi

关于c++:红黑树

红黑树概念 红黑树是一种二叉搜寻树,在每个节点上减少一个存储位,用来存储节点色彩(红或黑)通过对通过对色彩的限度,确保任意一条从根节点到叶子节点的门路不会比其余门路长出两倍(即最长门路最多只能是最短门路的两倍)红黑树通过对色彩的管制,从而达到近似均衡(AVL是严格均衡的)AVL树通过旋转形式来管制均衡,而其搜寻效率上跟红黑树差不多(红黑树效率要略低)尽管红黑树效率略低,然而AVL树旋转次数过多,综合来说红黑树更好一些。红黑树性质每个节点只能是红色或者彩色。根节点是彩色。如果一个节点是红色,那么它的两个子节点就是彩色(如果一个节点是彩色,那么它的子节点能够是红色也能够是彩色)(即不存在间断的红色节点)对于每个节点,从该节点到其后辈的所有叶子节点的门路上,每条门路的彩色节点数雷同(包含最初的空节点)所有的空节点都是彩色。通过上述规定的管制,就能够保障红黑树的最长门路中节点个数不会超过最短门路节点数的两倍。最长门路一黑一红,最短门路全黑。红黑树节点定义形式个别在插入新节点时,默认插入节点色彩为红色,因为默认为彩色节点,肯定会毁坏规定四,影响较大,然而默认为红色节点,只是有可能毁坏规定三。template<class K,class V>struct RBTreeNode{ RBTreeNode<K, V>* _left; RBTreeNode<K, V>* _right; RBTreeNode<K, V>* _parent; pair<K, V> _kv; //键值对,存储数据 Colour _col; //存储色彩 RBTreeNode(const pair<K, V>& kv) :_left(nullptr) , _right(nullptr) , _parent(nullptr) , _kv(kv) , _col(RED) //默认节点色彩为红色 { }};红黑树新增节点的三种状况cur为新增节点,p 为父节点,g为祖父节点,u为叔叔节点(要害看叔叔节点的色彩)蓝色方框为红黑子树。状况一:cur为红(在p的左右皆可),p为红,g为黑,u存在且为红解决办法:变色将父节点和叔叔节点都变为黑,并且将祖父节点变为红如果祖父节点的父节点也为红,违反规定三,则持续向上进行变换。如果祖父节点为根节点,违反规定二,则再将祖父节点变为黑。状况二:cur为红,且在p的右边,p为红,g为黑,u不存在或者存在且为黑cur在父节点的右边。解决办法:单右旋+变色(祖孙三代是直线关系)进行右单旋转将父节点变为黑,祖父节点变为红。状况三:cur为红,且在p的左边,p为红,g为黑,u不存在或者存在且为黑解决办法:双旋转+变色(祖孙三代是折线关系)先进行左单旋,再进行右单旋,最初再变色。源码地址gitee:https://gitee.com/BJFyfwl/Lin...

September 29, 2022 · 1 min · jiezi

关于c++:项目篇高并发内存池

根底概念池化技术所谓池化技术,就是程序先向零碎申请适量的资源,而后本人治理,当程序中须要申请内存时,不是间接向操作系统申请,而是间接从内存池中获取,开释内存时也不是将内存返回给操作系统,而是返回内存池中。因为每次申请该资源都有较大的开销,这样提前申请好了,应用时就会十分快捷,可能大大提高程序运行效率。在计算机中有很多应用这种池技术的中央,例如线程池、连接池等。动态内存申请mallocC++中动静申请内存都是通过malloc去申请的,但实际上咱们并不是间接去堆中获取内存的,而malloc就是一个内存池。malloc() 相当于向零碎 “零售” 了一块较大的内存空间,而后“批发” 给程序应用,当全副应用完或者程序有大量内存需要时,再依据需要向操作系统申请内存。定长内存池设计设计思路开拓内存: 应用malloc开拓一大块内存,让_memory指针指向这个大块内存_memory 设置为char* 类型,是为了不便切割时_memory向后挪动多少字节数。申请内存: 将_memory强转为对应类型,而后赋值给对方,_memory指针向后挪动对应字节数即可。如果有存在曾经切割好的小块内存,则优先应用小块内存。开释内存: 用类型链表的构造来进行存储。用以后小块内存的头4字节存储下一个小块内存的地址,最初用_freeList指针指向第一个小块内存的地址(并不是将内存开释给操作系统)所以开拓内存时,开拓的内存大小必须大于或等于一个指针类型的大小。代码地位:高并发内存池我的项目中的ObjectPool.h 文件。高并发内存池整体设计框架三层设计思路第一层:thread cache(线程缓存): 每个线程独享一个thread cache,用于小于256k的内存分配情况,线程从这里申请内存不须要加锁(因为其余线程无法访问以后线程的 thread cache,没有竞争关系)第二层:central cache(核心缓存): 所有线程共享一个central cache,thread cache 是按需从central cache中获取对象,central cache在适合的时候会发出thread cache中的对象,防止一个线程占用太多资源。central cache 是所有线程共享的,所以存在竞争关系,须要加锁;这里应用的锁是桶锁,并且因为只有thread cache没有内存时才会申请内存,所以这里竞争不会太强烈。第三层:page cache(页缓存): 页缓存存储的内存是以页为单位进行存储的及调配的。central cache没有内存时,则会从page cache中申请肯定数量的page,并切割成定长大小的小内存块。当一个span的几个跨度页的对象都回收后,page cache会回收central cache满足条件的span对象,并且合并相邻的页,组成更大的页,缓解内存碎片的问题。 thread cache 设计思路(线程缓存)线程申请内存: 线程申请内存时,会有不同规格的内存申请(4字节、5字节等),依据范畴划定不同的自在链表,设计多个自在链表治理不同规格的内存小块。本质就相当于应用多个定长内存池的自在链表每个内存小块采纳向上对齐准则(可能会呈现多申请内存的状况,这就是内碎片)例如: 须要9字节,则开拓一个大小为2个8字节的空间的节点须要100字节,则开拓一个大小为13个8字节的空间的节点。线程对齐规定: 整体管制在最多10%左右的内碎片节约总计设计208个桶[0,15]个桶,每个桶的对齐数相差8字节(最高128字节对齐)[16,71]个桶,每个桶的对齐数相差16字节(最高1024字节对齐)以此类推 留神:_freeLists是一个数组,每个元素都是自在链表类型(即存储自在链表的头结点)线程开释内存 开释内存后:采纳自在链表的构造来治理切好的小块内存(每一个切分好的小块内存就是一个节点)具体方法是:用切分好的小块内存的前4字节或8字节来存储下一个小块内存的地址。插入节点时,采纳头插的形式。线程缓存无锁设计(TLS)TLS:thread local storage 线程本地存储(linux和Windows下有各自的TLS)TLS是一种变量的存储形式,这个变量在它所在的线程内是全局可拜访的,然而不能被其余线程拜访,这样就保障了线程的独立性。动态TLS应用办法: _declspec(thread) DWORD data=0;申明了一个 _declspec(thread) 类型的变量,会为每一个线程创立一个独自的拷贝。原理: 在x86 CPU上,将为每次援用的动态TLS变量生成3个辅助机器指令如果在过程中创立子线程,那么零碎将会捕捉它并且主动调配一另一个内存块,以便寄存新线程的动态TLS变量。//每个线程刚创立时,就会取得这个指针,每个线程的指针是不同的。static _declspec(thread) ThreadCache* pTLSThreadCache = nullptr;//static 润饰,能够保障变量只在以后文件可见。central cache设计思路(核心缓存)central cache也是一个哈希桶构造,每个哈希桶地位挂载的是SpanList自在链表构造。Span治理的是以页为单位的大块内存(一页为8kb(32位零碎下))每个Span中的大内存依据映射关系被切成了一个个的小块内存对象,而后挂载在Span上。因为核心缓存是所有线程共享的,只须要定义一个对象,所以这里须要将 central cache 设计为单例模式(这里采纳饿汉模式的设计办法)留神: span是双向链表,而span下挂载的小块内存对象是单链表。核心缓存须要加桶锁。_spanLists 是一个数组,数组中每个元素都是一个span自在链表的_head头指针。每个span又是一个单向自在链表。 内存申请 当thread cache中没有内存时,就会批量向central cache申请一些内存对象,从对应的span中取出小块内存对象给thread cache,这个过程是须要加锁的(加桶锁)这里批量获取对象的数量应用了相似网络tcp协定拥塞管制的慢开始算法。如果所有的span都为空了(即central cache应用完了),则将空的span链在一起,向page cache申请一个span对象,span对象中是一些以页为单位的内存,须要切成对应的小块内存对象,并链接起来,挂到span中。central cache中每一个span都有一个use_count,调配一个对象给thread cache,就加加。内存开释: ...

September 28, 2022 · 1 min · jiezi

关于c++:百度工程师带你探秘C内存管理理论篇

作者 | daydreamer 在互联网的服务中,C++罕用于搭建高性能、高并发、大流量、低延时的后端服务。如何正当的分配内存满足零碎高性能需要是一个高频且重要的话题,而且因为内存本身的特点和理论问题的简单,组合出了诸多难题。 咱们能够对内存进行多种类型的划分,从内存申请大小来看: 小对象调配:小于4倍内存页大小的内存调配,在4KiB页大小状况下,<16KiB算作小对象调配;大对象调配:大于等于4倍内存页大小的内存调配,在4KiB页大小状况下,>=16KiB算作大对象调配。从一块内存的被持有时长来看: 后端一次申请内甚至更短时间申请和开释任意工夫窗口内内存持有和更新简直与利用过程等长的内存持有和更新某个过程沦亡后一段时间内,由该过程申请的仍具备意义的内存持有和开释当然还能够依照内存申请开释频率、读写频率进行进一步的分类。 内存治理服务于利用零碎,目标是帮助零碎更好的解决瓶颈问题,比方对于『如何升高后端响应的提早和进步稳定性』内存治理可能要思考的是: 解决内存读写并发(读频繁or写频繁)升高响应工夫和CPU耗费应用层的内存的池化复用底层内存向零碎申请的内存块大小及内存碎片化每一个问题开展可能都是一个比拟大的话题,本文作为系列文章《探秘C++内存治理》的开篇,先介绍Linux C++程序内存治理的实践根底。后续会持续解密C++程序罕用的内存治理库的实现原理,包含ptmalloc,jemalloc,tcmalloc等,介绍以后业界风行的内存分配器如何治理C++程序的内存。理解内存分配器原理,更有助于工程师在实践中升高解决内存应用问题的老本,依据零碎量身打造应用层的内存管理体系。 一、Linux内存治理Linux自底向上大抵能够被划分为: 硬件(Physical Hardware)内核层(Kernel Space)用户层(User Space) △图1:Linux构造 内核模块在内核空间中运行,应用程序在用户空间中运行,二者的内存地址空间不重叠。这种办法确保在用户空间中运行的应用程序具备统一的硬件视图,而与硬件平台无关。用户空间通过应用零碎调用以可控的形式使内核服务,如:陷入内核态,解决缺页中断。 Linux的内存管理系统自底向上大抵能够被划分为: 内核层内存治理 : 在 Linux 内核中 , 通过内存调配函数治理内存:kmalloc()/\_\_get\_free\_pages():申请较小内存(kmalloc()以字节为单位,\_\_get\_free\_pages()以一页128K为单位),申请的内存位于物理内存的映射区域,而且在物理上也是间断的,它们与实在的物理地址只有一个固定的偏移。vmalloc():申请较大内存,虚拟内存空间给出一块间断的内存区,但不保障物理内存间断,开销远大于\_\_get\_free\_pages(),须要建设新的页表。用户层内存治理:通过调用零碎调用函数(brk、mmap等),实现罕用的内存治理接口(malloc, free, realloc, calloc)治理内存;经典内存治理库ptmalloc2、tcmalloc、jemalloc。应用程序通过内存治理库或间接调用零碎内存治理函数分配内存,依据应用程序自身的程序个性进行应用,如:单个变量内存申请和开释、内存池化复用等。至此单个过程能够应用Linux提供的内存划分顺利的运行,从用户程序来看Linux过程的内存模型大抵如下所示: △图2:Linux过程的内存模型 栈区(Stack):存储程序执行期间的本地变量和函数的参数,从高地址向低地址成长堆区(Heap): 动态内存调配区域,通过malloc、new、free和delete等函数治理在规范C库中,提供了malloc/free函数调配开释内存,这些函数的底层是基于brk/mmap这些零碎调用实现的,对照图2来看: brk(): 用于申请和开释小内存。数据段的开端,堆内存的开始,叫做brk(program break)。通过设置heap的完结地址,将该地址向高或低挪动实现堆内存的扩张或膨胀。低地址内存必须在高地址内存的开释之后能力失去的开释,被标记为闲暇区的低地址,无奈被合并,如果后续再来内存空间的申请大于此闲暇区,这部分将成为内存空洞。默认状况下,当最高地址空间的闲暇内存超过128K(可由M\_TRIM\_THRESHOLD选项调节)时,执行内存压缩操作(trim)。mmap():用于申请大内存。mmap(memory map)是一种内存映射文件的办法,行将一个文件或者其它对象映射到过程的虚拟地址空间中(堆和栈两头的文件映射区域 Memory Mapping Segment),实现文件磁盘地址和过程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,过程就能够采纳指针的形式读写操作这一段内存,而零碎会主动回写脏页面到对应的文件磁盘上,内核空间对这段区域的批改也间接反映用户空间,从而能够实现不同过程间的文件共享。大于 128 K 的内存,应用零碎调用mmap()分配内存。与 brk() 分配内存不同的是,mmap() 调配的内存能够独自开释。munmp():开释有mmap()创立的这段内存空间。但在对于多个同时运行的过程,零碎仍需解决无限的物理内存和增长的内存地址等问题。那么当Linux存在多个同时运行的过程时,一次内存的调配过程具体都通过哪些过程呢?古代Linux零碎上内存的调配次要过程如下[1] : 应用程序通过调用内存调配函数,零碎调用brk或者mmap进行内存调配,申请虚拟内存地址空间。虚拟内存至物理内存映射处理过程,通过申请MMU调配单元,依据虚拟地址计算出该地址所属的页面,再依据页面映射表的起始地址计算出该页面映射表(PageTable)项所在的物理地址,依据物理地址在高速缓存的TLB中寻找该表项的内容,如果该表项不在TLB中,就从内存将其内容装载到TLB中。 △图3:Linux内存分配机制(虚构+物理映射) 对于内存调配过程中波及到工具进一步分析: 虚拟内存(Virtual Memory):古代操作系统广泛应用的一种技术,每个过程有用独立的逻辑地址空间,内存被分为大小相等的多个块,称为页(Page)。每个页都是一段间断的地址,对应物理内存上的一块称为页框,通常页和页框大小相等。虚拟内存使得多个虚构页面共享同一个物理页面,而内核和用户过程、不同用户过程隔离。MMU(Memory-Management Unit):内存治理单元,负责管理虚拟地址到物理地址的内存映射,实现各个用户过程都领有本人的独立的地址空间,提供硬件机制的内存拜访权限查看,爱护每个过程所用的内存不会被其余的过程所毁坏。PageTable:虚拟内存至物理内存页面映射关系存储单元。TLB(Translation Lookaside Buffer):高速虚构地址映射缓存, 次要为了晋升MMU地址映射解决效率,加了缓存机制,如果存在即可间接取出映射地址供应用。这里要提到一个很重要的概念,内存的提早调配,只有在真正拜访一个地址的时候才建设这个地址的物理映射,这是 Linux 内存治理的根本思维之一。Linux 内核在用户申请内存的时候,只是调配了虚拟内存,并没有调配理论物理内存;当用户第一次应用这块内存的时候,内核会产生缺页中断,调配物理内存,建设虚拟内存和物理内存之间的映射关系。当一个过程产生缺页中断的时候,过程会陷入内核态,执行以下操作: 查看要拜访的虚拟地址是否非法查找/调配一个物理页填充物理页内容建设映射关系(虚拟地址到物理地址)从新执行触发缺页中断的指令如果填充物理页的过程须要读取磁盘,那这次缺页中断是majflt,否则是minflt。咱们须要重点关注majflt的值,因为majflt对于性能的侵害是致命的,随机读一次磁盘的耗时数量级在几个毫秒,而minflt只有在大量的时候才会对性能产生影响。 二、总结通过对Linux内存治理的介绍,咱们能够看到内存治理须要解决的问题: 调用零碎提供的无限接口操作虚存读写衡量单次调配较大内存和屡次调配较少内存带来老本:管制缺页中断(尤其是majflt)vs 过程占用过多内存升高内存碎片升高内存治理库本身带来的额定损耗在接下来的几篇文章将就ptmalloc,jemalloc,tcmalloc几个经典内存治理库,与大家进一步探讨C++程序罕用的内存治理库的实现原理。 ---------- END ---------- 相干参考: [1] 《Linux通明大页机制在云上大规模集群实际介绍》:https://mp.weixin.qq.com/s/hGjADS9tdHeqS9XR4pkh\_w [2] Writing a Linux Kernel Module — Part 1: Introduction: http://derekmolloy.ie/writing... ...

September 28, 2022 · 1 min · jiezi

关于c++:AVL树

AVL树性质它的左右子树都是AVL树左右子树高度之差的绝对值不超过1(右子树高度 - 左子树高度)(也称为均衡因子)每个节点都有一个均衡因子个别AVL树都是三叉链(左右节点指针和父亲节点指针)AVL树高度为 O(logN)AVL树的工夫复杂度为O(logN)。均衡因子的更新准则: 如果新增节点在父节点的右边,则父节点的均衡因子减1;顺次向上更新如果新增节点在父节点的左边,则父节点的均衡因子加1;顺次向上更新直到以后节点的均衡因子为0才不向上持续更新了如果均衡因子为-2或2,则须要旋转。而后在判断是否须要持续更新。AVL树节点的定义形式template<class K,class V>struct AVLTreeNode //建设节点{ AVLTreeNode<K, V>* _left; AVLTreeNode<K, V>* _right; AVLTreeNode<K, V>* _parent; int _bf; //均衡因子 pair<K, V> _kv; //键值对,存储数据 AVLTreeNode(const pair<K, V>& kv) //构造函数 :_left(nullptr) ,_right(nullptr) ,_parent(nullptr) ,_bf(0) ,_kv(kv) {}};AVL树的四种旋转形式为什么要旋转当插入一个节点时,直接插入可能会导致均衡被毁坏(插入节点的所有先人节点的均衡因子可能会扭转)这时就须要将数据进行旋转例如:当插入 30 节点时,这个树就不是AVL树了,所以将其进行旋转,失去左边的AVL树。右单旋 右单旋代码实现 //右单旋 void RotateR(Node* parent) { Node* subL = parent->_left; Node* subLR = subL->_right; Node* parent_parent = parent->_parent; parent->_left = subLR; if (subLR) subLR->_parent = parent; subL->_right = parent; parent->_parent = subL; if (parent == _root) { _root = subL; _root->_parent = nullptr; } else { if (parent_parent->_left == parent) parent_parent->_left = subL; else parent_parent->_right = subL; subL->_parent = parent_parent; } subL->_bf = 0; parent->_bf = 0; }左单旋 ...

September 27, 2022 · 2 min · jiezi

关于c++:本周三全球C大会8大主题近40场专题演讲盛大开启龙蜥2位技术专家参加

零碎级软件是数字世界的基础设施,C++ 自 1985 年由 Bjarne Stroustrup 博士在贝尔实验室创造以来,始终被誉为零碎级编程“皇冠上的明珠”。2022 年 9 月 28-29 日,由高端 IT 征询与教育平台 Boolan 主办的「2022 寰球 C++ 及系统软件技术大会」将于上海隆重召开。本次大会特邀 C++ 之父、美国工程院、ACM、IEEE 院士 Bjarne Stroustrup 以及来自国内外 C++ 与系统软件畛域的巨匠、专家、学者齐聚一堂。 系统软件畛域规模最大、阵容最强、干货最多的大会将围绕 C++ 20 新规范、工程与工具链、架构与设计演变、品质与效力、高性能与低时延、零碎级软件等 8 大主题、40+ 技术大咖及上千位业界同仁,深度探讨 C++ 与零碎级软件技术畛域的最佳工程实际和前沿办法。 龙蜥社区两位资深技术专家也将参加此次大会演讲,将与各领域专家、学者探讨交换,分享内容包含 eBPF 工具的开发和资源优化在多内核版本的实际、现代化工具链在大规模 C++ 我的项目中的实际。 参会嘉宾和议题如下: eBPF 工具的开发和资源优化在多内核版本的实际工夫:分会场A 9 月 28 日下午 16:50-17:40 嘉宾:毛文安,龙蜥社区零碎运维 SIG 负责人 Linux 内核版本经验了 3.x 向 4.x 到 5.x 演进,eBPF 技术的反对也是从 4.x 开始欠缺起来,目前高版本内核曾经反对纯 CORE 形式,而云上服务器有大量的 3.10 内核版本是不反对 eBPF 的,为了让咱们现有的 eBPF 工具在这些存量机器得以反对,享受到 eBPF 带来的红利,咱们移植了eBPF技术到低版本内核,保障一个工具可运行于低、中、高的内核版本。 ...

September 27, 2022 · 1 min · jiezi

关于c++:视频结构化-AI-推理流程

「视频结构化」是一种 AI 落地的工程化实现,目标是把 AI 模型推理流程可能一般化。它输出视频,输入结构化数据,将后果给到业务零碎去造成某些行业的解决方案。 换个角度,如果你想用摄像头来实现某些智能化监控、预警等,那么「视频结构化」可能就是你要用到的技术计划。 不过,也不肯定须要本人去实现,因为各个芯片厂商可能都提供了相似的流程框架: 寒武纪 CNStreamNVIDIA DeepStream以上集体没用过,简略看了下,都受限于只能用厂商自家的芯片。集体教训来说,个别硬件还是须要多家可选的,本人实现一套「视频结构化」还是有必要的。 本文将介绍「视频结构化」的实现思路、技术架构,以及衍生的一些工作。 实现思路有一个 AI 模型与一段视频,如何进行推理呢? 视频流:OpenCV 关上视频流,获取图像帧前解决:图像 Resize 成模型输出的 Shape模型推理:AI 框架进行模型推理,失去输入后处理:将输入解决成冀望的信息 例如,指标检测:解析框的地位和类别,再 NMS 筛选以上是最根底的推理流程,实现得不错 简略工作,这样满足要求就行。但理论工作,可能: 输出 工作接管视频流 相机选型视频起源: 录制视频、RTSP 实时流帧率控制: 个别 5 fps,缩小计算多路并发: 多路视频,并行剖析硬件解码推理 前解决 输出调整: 缩放、转置Batch 合并硬件加速模型推理 硬件选型: Nvidia、华为昇腾、或其余模型解决: 裁剪、转换、量化模型编排: 多任务多模型,有先后关系后处理 输入解析: 推理后果,变为结构化数据硬件加速输入 后果推送其余 视频存储,License链路追踪,耗时剖析以上流程个别称为「视频结构化」:输出多路视频,进行实时剖析,最初输入结构化数据,给到业务零碎。 该流程,这里把它分为了输出、推理、输入,都是一个个工作节点,整体采纳 Pipeline 形式来编排 AI 推理工作。输入输出时,个别会用 RPC 或音讯队列来与业务零碎通信。 整体架构「视频结构化」整体架构,如下: 管道节点管道 Pipeline 这块是次要局部,其实现都是一个个节点: IN 工作接管;视频流解码;帧率控制推理 推理引擎做模型推理,后果进结构化数据;依编排往后持续追踪 追踪依赖推理出的特色;业务不须要,就不编排OUT 后果推送;要预览播放的话,进行视频流编码节点就是个生产消费者,用个阻塞队列很快就能实现。节点间组成一个树,也就是工作编排的后果。节点会有输入输出差别,要约定分明或分几个类型。 节点流程:音讯队列有工作,取出执行,后果进结构化数据,最初发给下一节点的音讯队列。 节点的线程数、队列下限,都可做配置。根据耗时剖析,能够优化调整。 GStreamer 的 pipeline + plugin 的技术架构值得学习。集体没深刻理解,所以不好具体评估,倒见过在输出做插件化解码。NVIDIA DeepStream 间接就基于 GStreamer 开发的。构造数据结构化数据,在整个 Pipeline 里是一直追加欠缺的过程,最初输入时个别 JSON 化推送。 ...

September 23, 2022 · 1 min · jiezi

关于c++:2022升级百度大牛带你结合实践重学C完结无密

download:2022降级百度大牛带你联合实际重学C++完结无密哈希表查找哈希算法的定义与实现1哈希表查找定义哈希技术是在记录的存储地位和它的关键字之间建设一个确定的对应关系,使每个关键字对应一个存储地位。 存储地位=f(关键字) 对应关系称为哈希函数,也称为哈希函数。 哈希技术用于将记录存储在一个间断的存储空间中,称为哈希表或哈希表。哈希技术不仅是一种存储办法,也是一种搜寻办法。 Hash函数可能将两个或多个不同的关键字映射到同一个地址,称这些状况为抵触,而这些抵触的不同关键字称为同义词。 2哈希函数的构造方法3.1间接寻址办法对于关键字age,能够间接用age的数量作为地址,其中f(key)=key。 如果要统计1980年当前出世年份的人口,如下图所示,能够用年份减去1980作为出世年份关键字的地址。此时f(key)=key-1980。 间接关键字去除的线性函数值是哈希地址,哈希函数是: 间接寻址法的哈希函数简略、对立且不会引起抵触,但须要当时晓得关键字的散布,所以实用于小而间断的查找表。 3.2除法和余数法除余数法是结构哈希函数最罕用的办法。假如哈希表长度为M,取一个不大于M但最靠近或等于M的素数P,哈希函数为: 假如咱们有12个记录的关键字来结构哈希表,例如,咱们应用新办法,所以它存储在下标5处。 依据教训,如果哈希表长度为M,通常P是小于等于表长度的最小素数(最好靠近M)或者是不蕴含少于20个素数因子的合数。 解决哈希抵触的3种办法3.1凋谢地址办法3.1.1线性检测办法开放式寻址办法是一旦有抵触就寻找下一个空的散列地址。只有哈希表足够大,总是能够找到空的哈希地址,并且记录将被存储。 在一个简略的例子中,咱们的关键字集是,表长度是12。咱们应用散列函数。 计算前五个数时,都是哈希地址,没有抵触,间接存储。 计算key=37时,发现与25的地位抵触,于是从新计算,37存储在下标2的地位,如图。 当key=48时,咱们计算出和12所在的地位0抵触。持续算,和25的地位抵触,所以始终到都没有空缺,如图。 这种解决抵触的开放式寻址办法称为线性检测办法。 二次检测那时候叫二次检测法。减少正方形操作的目标是为了避免所有关键词都汇集在某个区域。 伪随机检测在有抵触的状况下,用随机函数计算位移,称为随机检测法。 3.2链接地址办法为了防止非同义词的抵触,所有的同义词都存储在一个线性链表中。 对于可能导致许多抵触的散列函数,链办法提供了不会找到地址的保障。 4哈希表的搜寻哈希查找依赖于三个因素:哈希函数、解决抵触的办法和填充因子。 填充因子表中记录的哈希表长度。 哈希表的均匀搜寻长度取决于哈希表的填充因子,而不是间接取决于或。 越大越满,抵触的可能性越大。 4.1哈希表搜索算法的实现哈希表的构造定义如下: 定义胜利1定义不胜利0define HASHSIZE 12 /将哈希表长度定义为数组的长度/定义NULLKEY -32768typedef int状态;/ Status是函数的类型,其值是函数后果状态码,如OK等。/ typedef构造{int elem/数据元素存储基址,动态分配数组*/int计数;/以后数据元素的数量/}哈希表; int m = 0;/哈希表长度,全局变量/哈希表初始化: /初始化哈希表/状态InitHashTable(HashTable *H){int I;m = HASHSIZEh-> count = m;h-> elem =(int )malloc(m sizeof(int));for(I = 0;我h-> elem[I]= null key;退货OK;}作为哈希函数的余数办法: /哈希函数/int Hash(int key){返回键% m;/除法和余数法/}哈希表插入算法: /将关键字插入哈希表/void InsertHash(HashTable *H,int key){int addr = Hash(key);/查找哈希地址/while (H->elem[addr]!= NULLKEY) /如果不为空,则抵触/{addr =(addr+1)% m;/凋谢寻址办法的线性检测/}h-> elem[addr]= key;/插入关键字,直到有空格为止/}在代码中插入关键字时,首先计算哈希地址。如果以后地址不是空关键字,则示意存在抵触。此时咱们应用线性检测的凋谢寻址办法进行重寻址,这里也能够改为链地址法等其余抵触解决办法。 ...

September 23, 2022 · 1 min · jiezi

关于c++:通用ORM的设计与实现

介绍咱们通用的ORM,基本模式都是想要脱离数据库的,简直都在编程语言层面建设模型,由程序去与数据库打交道。尽管脱离了数据库的具体操作,但咱们要建设各种模型文档,用代码去写表之间的关系等等操作,让初学者一时如坠云雾。我的想法是,将关系数据库领有的欠缺设计工具之劣势,来实现数据设计以提供构造信息,让json对象主动映射成为规范的SQL查问语句。只有咱们了解了规范的SQL语言,咱们就可能实现数据库查问操作。 依赖关系本我的项目依赖 自己的 另一个我的项目 Zjson,此我的项目提供简洁、不便、高效的Json库。该库使用方便,是一个单文件库,只须要下载并引入我的项目即可。具体信息请移步 gitee-Zjson 或 github-Zjson 。 设计思路ZORM 数据传递采纳json来实现,使数据规范能从最前端到最初端达到谐和对立。此我的项目指标,岂但在要C++中应用,还要作为动态链接库与node.js联合用应用,因而心愿能像javascript一样,简洁不便的操作json。所以后行建设了zjson库,作为此我的项目的后行我的项目。设计了数据库通用操作接口,实现与底层实现数据库的拆散。该接口提供了CURD规范拜访,以及批量插入和事务操作,根本能满足平时百分之九十以上的数据库操作。我的项目根本指标,反对Sqlite3,Mysql,Postges三种关系数据库,同时反对windows、linux和macOS。 我的项目进度当初曾经实现了sqlit3与mysql的所有性能,postgres也做了技术筹备。 我抉择的技术实现形式,基本上是最底层高效的形式。sqlit3 - sqllit3.h(官网的规范c接口);mysql - c api (MySQL Connector C 6.1);postgres - pqxx 。 工作列表: [x] Sqlite3 实现 [x] linux[x] windows[x] macos[x] Mysql 实现 [x] linux[x] windows[x] macos[ ] Pstgre 实现 [ ] linux[ ] windows[ ] macos数据库通用接口利用类间接操作这个通用接口,实现与底层实现数据库的拆散。该接口提供了CURD规范拜访,以及批量插入和事务操作,根本能满足平时百分之九十以上的数据库操作。 class ZORM_API Idb { public: virtual Json select(string tablename, Json& params, vector<string> fields = vector<string>(), Json values = Json(JsonType::Array)) = 0; virtual Json create(string tablename, Json& params) = 0; virtual Json update(string tablename, Json& params) = 0; virtual Json remove(string tablename, Json& params) = 0; virtual Json querySql(string sql, Json params = Json(), Json values = Json(JsonType::Array), vector<string> fields = vector<string>()) = 0; virtual Json execSql(string sql, Json params = Json(), Json values = Json(JsonType::Array)) = 0; virtual Json insertBatch(string tablename, Json& elements, string constraint = "id") = 0; virtual Json transGo(Json& sqls, bool isAsync = false) = 0; };实例结构全局查问开关变量:DbLogClose : sql 查问语句显示开关parameterized : 是否应用参数化查问Sqlite3: Json options; options.addSubitem("connString", "./db.db"); //数据库地位 options.addSubitem("DbLogClose", false); //显示查问语句 options.addSubitem("parameterized", false); //不应用参数化查问 DbBase* db = new DbBase("sqlite3", options);Mysql: Json options; options.addSubitem("db_host", "192.168.6.6"); //mysql服务IP options.addSubitem("db_port", 3306); //端口 options.addSubitem("db_name", "dbtest"); //数据库名称 options.addSubitem("db_user", "root"); //注销用户名 options.addSubitem("db_pass", "123456"); //明码 options.addSubitem("db_char", "utf8mb4"); //连贯字符设定[可选] options.addSubitem("db_conn", 5); //连接池配置[可选],默认为2 options.addSubitem("DbLogClose", true); //不显示查问语句 options.addSubitem("parameterized", true); //应用参数化查问 DbBase* db = new DbBase("mysql", options);智能查问形式设计查问保留字:page, size, sort, fuzzy, lks, ins, ors, count, sum, grouppage, size, sort, 分页排序 在sqlit3与mysql中这比拟好实现,limit来分页是很不便的,排序只需将参数间接拼接到order by后就好了。 查问示例: ...

September 20, 2022 · 3 min · jiezi

关于c++:2022升级百度大牛带你结合实践重学C完结无密含资料

download:2022降级百度大牛带你联合实际重学C++完结无密含材料一条SQL语句从头到尾1.一段SQL是怎么诞生的?SQL语句都诞生在客户端。生成一条SQL次要有两种形式,一种是开发人员自己手工编写,另一种是相干的ORM框架主动生成。一般MySQL运行过程中收到的SQL大多是ORM框架生成的,比如Java中的MyBatis和Hibernate框架。同时,SQL生成的时机一般与用户的请求无关。当用户在零碎中执行操作时,通常会生成一条SQL。例如,咱们在阅读器上输出以下URL: 此时会先请求掘金的服务器,而后掘金外部实现中的ORM框架会根据请求的参数生成一条SQL,类似于上面的伪SQL: select * from金爵_article其中userid = 862486453028888 这个SQL大抵意义是:根据用户请求的“作者ID”,查问掘金数据库文章表中该作者的所有文章信息。从下面的案例可能显著感觉到,在用户阅读器上看到的数据一般来自于数据库,而数据库执行的SQL来自于用户的操作。这两者是互补的,包含任何写操作(增加、删除、更改),本质上也会转换成SQL的片段。让我举一个简略的例子: 请求URL(请求URL)https://www.xxx.com/user/regi... 请求参数(请求参数){User_name:“竹子爱熊猫”,user _ pwd:“123456”,用户_性别:“男”,用户_电话:“18888888888”,......} 这里对用户明码的处理不够谨严,不做加密也不必在意~复制代码例如,在上述用户注册的情况下,当用户点击网页上的“注册”按钮时,将向目标网站的服务器发送post请求,而后将根据请求参数生成一条SQL,如下所示:insert into table_user(用户名,用户明码,用户性别,用户电话,....)价值观(“竹子爱熊猫”、“123456”、“男”、“188888888”,...);复制代码也就是说,一条SQL的诞生源于一个用户的请求。在开发程序时,SQL的一般逻辑会由业务层的代码决定,而具体的SQL语句会根据用户的请求参数和事先定制的“SQL骨架”做出。当然,在Java程序或者其余语言编写的程序中,只能生成SQL,SQL的真正执行需要数据库来实现。第二,SQL在执行之前将经历的一个过程通过上一步,一个完整的SQL就诞生了。为了让SQL失常执行,咱们将首先获得一个数据库连接对象。上一篇对于MySQL架构的文章,已经讲过MySQL的连接层有一个叫“连接池”的小工具的保护,不过相信大家都接触过这个货色,比如C3P0,德鲁伊,DBCP等等在Java里。 至此,咱们可能在这里思考一个问题。数据库保护自己的连接池,为什么咱们还需要在MySQL客户端保护一个数据库连接池?接下来咱们聊聊。 2.1、数据库连接池的必要性家喻户晓,当你要用Java创建数据库连接时,首先会读取配置文件中的连接地址、账号密码等信息,而后发动网络请求,根据配置的地址信息获取数据库连接对象。在这个过程中,因为涉及到网络请求,此时必然会经历TCP三次握手的过程。同时,在获得连接对象并实现SQL操作后,将开释数据库连接。这时分就需要经历TCP挥动四次的过程。 从下面的描述中可能清晰地感知到,Java中创建和敞开数据库连接的过程实际上耗费了大量的成本,而且程序上线后,还需要频繁的数据库操作。所以,如果每次操作数据库都获得一个新的连接对象,那么整个Java程序至多有四分之一的工夫要做TCP三次握手/四次wave的工作,对整个零碎的后果不堪设想。.... 正是因为以上原因,才出现了家喻户晓的“数据库连接池”。“数据库连接池”的思维和“线程池”是一样的,会把数据库连接到这个宝贵的资源上,用池技术来保护这个资源。也意味着当前需要进行数据库操作时,不需要自己建立连接,而是可能间接从“数据库连接池”中获取,用完之后放回连接池,达到重用的成果。 当然,连接池中保护的连接对象不会一直存在。当长时间不执行SQL操作时,连接池也会销毁这些连接对象,必要时再从新创建。然而什么时候创建,什么时候销毁,限度连接数等等,都是交给连接池来实现,不需要开发者自己关注。 好了~,回到后面抛出的问题,为什么需要用MySQL连接池在客户端保护一个连接池? 这个问题相信每个人心里都有一些答案。原因很简略。两者都使用池化技术来重用资源,俭约开销,提高性能,但针对的方向不同。 MySQL的连接池次要是为了重用线程,因为每一个数据库连接都会被MySQL中的一个线程保护,而每一次连接对象调配给一个客户端,都需要经历创建线程、调配堆栈空间这样沉重的工作...这个过程需要工夫,资源开销也不小,所以MySQL通过使用池化技术来解决这些问题。客户端的连接池次要是为了重用数据库连接,因为每一个SQL操作都需要经历TCP三次握手/四波的过程,同样耗时耗力,占用资源。所以也采纳了池化技术来解决这个问题。 其实也可能这样理解,MySQL连接池保护的是工作线程,而客户端连接池保护的是网络连接。 2.2.在执行SQL之前会发生什么回到本文的主题,当生成完整的SQL时,咱们将首先尝试在连接池中获取一个连接对象。接下来会发生什么? 在尝试从连接池中获取连接时,如果此时连接池中有空闲的连接,可能间接获取重用。但如果不是,你首先要判断以后池中的连接数是否达到了最大数量。如果连接数已满,以后线程需要等待其余线程开释连接对象。如果没有,您可能间接创建一个新的数据库连接来使用。 假设此时连接池中没有空闲的连接,需要再次创建新的连接,那么首先会发动一个网络请求来建立连接。 ①首先,将考据客户端的用户名和明码是否正确: 如果用户名不存在或明码谬误,将抛出错误代码1045和谬误消息。如果用户名和明码通过考据,请转到步骤②。 ②必定MySQL连接池中是否有空闲线程: 存在:间接从连接池中调配一个空闲线程来保护以后客户端的连接。否:创建一个新的工作线程(映射内核线程,调配堆栈空间...). worker线程会先查问MySQL自己的用户权限表,获取以后登录用户的权限信息,并进行授权。 至此,执行SQL前的筹备工作已经实现,执行SQL的通道已经打开。下一步是筹备执行SQL语句,工作线程将等待客户端传送SQL。三。SQL语句是如何在数据库中执行的?通过连接层的一系列工作,客户端会通过连接发送要执行的SQL语句,而后由MySQL服务层进行处理。然而根据用户的操作不同,MySQL执行SQL语句时会有一些区别,SQL语句指的是读操作和写操作。这两条SQL语句的执行过程是不同的。咱们先来看看select语句的执行过程。3.1.一个查问SQL的执行过程在分析查问SQL的执行过程之前,咱们先模拟一个案例进行后续分析: SQL语句Select id from ZZ _ user 其中user sex =男性,user_name =竹四号";-表格数据 +|用户标识|用户名|用户性别|用户电话|+| 1 |竹① |男| 1888888888 || 2 |竹② |男| 1358888888 || 3 |竹③ |男| 1568888888 || 4 |熊猫① |女| 1348888888 || 5 |熊猫② |女| 1858888888 || 6 |竹④ |男| 17777777 || 7 |熊猫③ |女| 166666666 |+

September 19, 2022 · 1 min · jiezi

关于c#:开源福利-FreeRedis-历时两年正式发布-v10-CNET-Redis-Client

前言.NET 下 RedisClient SDK 抉择挺多,国人罕用收费的有 StackExchange.Redis/CSRedis/Newlife.Redis,免费的有 ServiceStack.Redis。 如果你是 CSRedis 或 ServiceStack.Redis 粉,那么肯定要不要错过关注 FreeRedis,它们的 API 十分类似,办法名、参数与 redis.io 官网命令文档保持一致,防止了二次转换的了解老本。 redis 命令可是有靠近300个呢~~~ 提醒:CSRedisCore 与 FreeRedis 是同一个作者,后者是基于 redis6.0 个性从新打造,解决了 CSRedisCore 的一些老问题,扩展性更强。 开源理念FreeRedis 的命名来自,“自在”、“收费”,它和名字与 FreeSql 是一个理念,繁难是他们统一的追寻方向,最低可反对 .NET Framework 4.0 运行环境,反对到 Redis-server 8.0(超时空版本)。 开源地址:https://github.com/2881099/FreeRedis FreeRedis 以最宽松的开源协定 MIT 开源,从第一个版本 v0.0.1 公布至今已有 22个月,工夫验证了其可靠性,是时候正式公布 v1.0 版本公开给大家,大家做 .neter 不容易,多一个抉择多一条路。 因为之前异步办法的优化始终未凋谢,v1.0 正式凋谢异步办法FreeRedis 整个源码是零依赖,应用它只会在 bin 目录产生一个 FreeRedis.dll,十分的轻量级,并且其性能十分弱小: <h1> FreeRedis </h1> 基于 .NET 的 Redis 客户端,反对 .NET Core 2.1+、.NET Framework 4.0+ 以及 Xamarin。 ...

September 18, 2022 · 2 min · jiezi

关于c++:2022升级百度大牛带你结合实践重学C含资料

download:2022降级百度大牛带你联合实际重学C++含材料5 Spring5源代码16-@EnableWebMvc正文原理1.需要和運用一旦我們將九個自定義組件放入容器,DispatcherServlet就會初始化,以查看容器中是否有我們自己的組件,因此我們不需要自己的默許組件。我們的許多默許功能都喪失了。我們的期望: 您自己的組件能夠失效。SpringMVC的默許還是管用的。能夠運用@ enablewemvc+webmvconfiguration。@EnableWebMVC會導入9個組件到容器中,並且都有條目【我們能夠用WebMvcConfigurer自定義】,而不是默許運用配置文件。 2.@EnableWebMvc@保留(RetentionPolicy。運轉時間)@Target(ElementType。類型)@已記载@ Import(delegatingwebmvc configuration . class)public @interface EnableWebMvc {}復製代码 我們發現,實践上是經過@Import正文在容器中注册了一個組件delegatingwebmvconfiguration,所以现在的核心是delegatingwebmvconfiguration類做了什麼? 3.托付web MVC配置 兩個感知接口自動將ApplicationContext對象和ServletContext對象注入該組件。现在我們要帶著兩個問題來看看這類源代码? 爲什麼這個組件能夠讓自定義配置類失效?爲此組件定義了哪些默許配置? 3.1托付webmvconfiguration源代码DelegatingWebMvcConfiguration類非常简單,只有一個字段配置器,它保存所有的配置類對象。另外要注意一個辦法,set configurator(list configurator)辦法,用@Autowired(required = false)正文,會自動執行。@ Configuration(proxybean methods = false)公共類托付WebMvcConfiguration擴展WebMvcConfigurationSupport { //組合模式,組合所有配置類。private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite(); /***此處增加了正文@Autowired(必填= false)。*然前办法將在屬性填充階段執行,其中辦法參數來自容器。*會自動沈著器中找到匹配類型的bean,然後反映執行辦法。*/@自動連線(必须=假)公共void匯合配置器(列表配置器){如果(!CollectionUtils.isEmpty(配置器)){//將容器中的所有WebMvcConfigurer對象放入WebMvcConfigurerCompositethis . configurers . addwebmvc configurers(配置器);}} /**/ /***以下辦法类似。*向WebMvcConfigurerComposite的每個配置類增加配置的詳細過程參見3.1.1。*/@掩蓋受維護的void配置路径匹配(路径匹配配置器配置器){this . configurers . configurepathmatch(configurer);} ... /**/ //此辦法將獲取配置類定義的獨一考證程序。@掩蓋@Nullable受維護的考證程序getValidator() {返回this . configurers . get validator();} //此辦法將獲取配置類定義的獨一MessageCodesResolver。@掩蓋@Nullable受維護的MessageCodesResolver getMessageCodesResolver(){返回this . configurers . getmessagecodesresolver();}}復製代码能夠看到,在DelegatingWebMvcConfiguration組件的屬性填充階段,會自動找到容器中所有類型爲WebMvcConfigurer的bean對象,然後以它們爲參數調用set configurators(list configurators)辦法,所有配置類對象都會放入WebMvcConfigurerComposite中。此外,它還重寫了父類的一些辦法(模板辦法模式)來向配置類注册配置,並獲取配置類中的一些配置對象,如Validator或MessageCodesResolver。3.2 WebMvcConfigurerComposite上面是這個類的源代码,辦法很简單,次要注意以下四點: 該類保存所有配置類對象。增加配置時,該配置將注册到所有配置類對象。getValidator()辦法只能由一個配置類重寫,並且只允許一個配置類返回一個Validator對象。getMessageCodesResolver()辦法只能由一個配置類重寫,並且只允許一個配置類返回MessageCodesResolver對象。 WebMvcConfigurerComposite類实现WebMvcConfigurer { //持有配置類對象公有最終列表托付= new ArrayList(); ...

September 18, 2022 · 1 min · jiezi

关于c:01C语言基础知识

最简略的C语言程序int main(){ return 0;}//该函数为入口函数//int 代表函数的返回值类型,return语句返回的数据类型要和它对应//main 函数名,main函数是C中惟一一个固定的函数名称,每个程序必须且只有一个main函数快捷键 CTRL+F5 是运行编写好的程序 查看编译后生成的exe文件: C语言中的头文件什么是头文件?头文件是他人给咱们写的代码,蕴含了头文件就能够应用其他人给咱们写好的代码,咱们通常将这些代码称为接口 如何蕴含头文件有两种形式 #include <xxx.h>:此种形式只在规范库中搜寻#include "xxx.h:此种形式依照所给门路查找头文件,首先搜寻规范库,再搜寻所给门路本人写的头文件也能放大规范库中去间接援用,然而不举荐随便更改规范库,容易导致隐患 如果须要援用能够通过配置我的项目属性的形式,减少规范库目录: 门路有两种模式: 绝对路径:带盘符相对路径 当前目录:./下层目录:../上下层目录:../../(有多少层,写多少个../)入口函数详解一个解决方案能够有多个我的项目 在以后我的项目右击,抉择【设为启动我的项目】后,能力应用CTRL+F5的形式调试本我的项目 入口函数的写法入口函数的写法多种多样,分为规范式和非标准式 tips:能够通过【工具】----【谬误查找】性能来查找错误代码的根本含意 system 函数作用:就是将命令字符串发送给零碎执行,相当于在cmd中执行无关命令 tips:应用时须要蕴含 stdlib.h头文件 利用场景: 执行exe文件执行cmd命令 常见cmd命令 pause:按任意键持续cls:清屏others程序运行和编译过程运行过程 从入口函数开始从上往下顺次执行程序生成 编辑--→ 生成 xxxooo.c(源文件)编译---→xxoo.obj(指标文件)链接----→xxoo.exe(二进制可执行文件)运行----→软件 gcc编译命令 gcc -E xxoo.c -o xxoo.i --→预处理文件.i gcc -S xxoo.i -o xxoo.s --→编译文件.s gcc -C xxoo.s -o xxoo.o --→二进制文件.o 谬误分类 编译谬误:所有编译谬误都能够通过VS查找定位,个别是因为语法问题引起的,另一些是因为不仔细引起的运行谬误:能够通过断点测试,代码量少间接F10逐句执行,代码量多,先预估谬误地位,再打断点测试逻辑谬误:只能通过解决,解决办法就是有错就改,改完再犯,千锤百炼# 课后作业 #include<stdio.h>#include<stdlib.h>int main(){ system("mode con lines=10 cols=40"); system("shutdown -s -t 60"); printf("60s内关机,按下任意键勾销!"); system("pause"); system("shutdown -a"); return 0;}

September 18, 2022 · 1 min · jiezi

关于c++:CC气象数据中心实战手把手教你做工业级项目源码齐全

download:C/C++气象数据中心实战,手把手教你做工业级我的项目(源码齐全)应用SpringBoot配置文件的具体阐明1.创立一个SpringBoot我的项目二。配置文件的类型从上一节的图中能够看出,src/main/resources目录中的application.properties文件是创立的默认全局配置文件。 这是一种以。属性后缀。 还有一种以结尾的YAML文件类型。yml suffix-application.yml/application.yaml. YAML是一种比属性格局年老得多的配置格局,属性格局在云原生中应用。三。配置文件#的语法格局3.1利用类型.属性#Properties是java中常见的配置文件类型,其语法格局为key=valve。复制 ` key=value '复制代码应用示例:复制 ` server.port = 80server.ip = 127.0.0.1 app.property.key = pronameapp.property.name = tomapp.list = 1,2,3 还有这个语法?增加启动命令:- spring.profiles.active=devspring . profiles . active = $ { spring . profiles . active } #读取启动命令参数 属性占位符:应用${var}语法来援用已定义属性的值。app.desc =您的姓名是${ app . property . name } `复制代码3.2 application.yml类型#将上述属性格局更改为yml格局:复制 `服务器:端口:80ip: 127.0.0.1 应用程序:属性:关键字:proname姓名:汤姆列表:[1,2,3]desc:你的名字是${app.property.name} 春天:个人资料:active:$ { spring . profiles . active } ` 0复制代码例如,对于一个数组,能够这样写:复制 `人:喜好:篮球跑步吗?-浏览复制代码你也能够这样写:复制 `人:喜好:[篮球、跑步、浏览]复制代码 YAML反对以下数据类型: 对象:键值对的汇合,也称为映射)/散列)/字典。数组:按顺序排列的一组值,也叫序列)/列表。标量:繁多的、不可分割的值。 3.3配置随机值SpringBoot外部提供了一个随机的。*属性,专门用于生成随机值。 属性random.int随机生成正负整数random.int(max)随机生成整数random.int(min[0,max]随机生成整数random.long随机生成正负长整数random.long(max)随机生成[0,长整数random区间的long(min,max)随机生成长整数random。[min,max]区间的UUID随机生成一个uuid字符串(包含'-'字符)。' '示意除上述字符之外的其余字符,用于随机生成32位字符串。配置示例:复制 ` int-val=${random.int}int-range-val=${random.int(2)}uuid-val=${random.uuid} `复制代码四。配置文件的加载程序#当SpringBoot启动时,以下地位的application.properties或application.yml将作为默认配置文件加载。 ...

September 17, 2022 · 1 min · jiezi

关于c++:名称空间

随着我的项目增大,不同的厂商的类库的名称可能会呈现抵触,比方,有可能两个类库同时都定义了名称为List、Tree、Node的类,然而定义的形式不兼容,为防止上述问题,C++提供了名称空间工具,来限定不同名称的作用域。 1、传统的C++名称空间 首先须要介绍三个术语:申明区域、潜在作用域,作用域 申明区域:申明区域为在其中进行申明的区域,比方在函数外申明全局变量,对于这种变量,其申明区域为其申明所在的文件。而对于在函数中申明的变量,其申明区域为其申明所在的代码块。 潜在作用域:变量的潜在作用域从申明点开始,到申明区域的结尾,所以潜在作用域比申明区域要小,起因是,变量只有定义了能力应用。 作用域:变量对程序而言可见的范畴被称为作用域。 潜在作用域和作用域的区别:在搞懂区别之前,须要阐明一个点,变量在潜在作用域内并不是始终都可见的,它会被嵌套申明中申明的同名变量暗藏,如果在代码块中申明的一个同名的变量将会暗藏代码块外申明的同名变量,此时在该代码块中,内部申明的变量就不可见了。用简略的话来说,潜在作用域一般来说是间断的一块,然而作用域有可能是断断续续的块连贯在一起的。 int main(){ int goo=0;//第一个goo作用域与潜在作用域同时失效 ...... for(int i=0;i<10;i++) { int temp=0; .... int goo=temp*1;//第二个goo作用域失效,暗藏第一个goo ....//在代码块完结处,第二个goo作用域完结,潜在作用域也完结。 } ......//第一个goo不在被暗藏,因而作用域持续 return 0;}2、新的名称空间个性 定义一种新的申明区域来创立命名的名称空间,提供一个申明名称的区域,以下代码应用新的关键字namespace创立了Jack名称空间。 namespace Jack{ double pail; void fetch(); int pal; struct Well{};} 名称空间既能够是全局的,也能够位于另一个名称空间,除了用户定义的名称空间外,还存在全局名称空间,全局变量即位于该全局名称空间,其对应于文件级申明区域。 名称空间是凋谢的,其既能够把名称退出到已有的名称空间中 namespace Jack{ char* goose(const char*);} 也能够在该文件前面再次应用Jack名称空间来提供该函数的代码 namespace Jack{ void fetch() { }} 拜访给定名称空间中的名称的办法为应用作用域解析运算符::。 1、using申明和using编译指令using申明:将特定的名称增加到它所属的申明区域中,下述代码中,在main函数中应用using申明Jill名称空间中的fetch变量,它防止了将另一个局部变量也命名为fetch,同时fetch将笼罩同名的全局变量。 namespace Jill{ double bucket(double n){} double fetch; struct Hill{}}char fetchint main(){ using Jill::fetch; double fetch; cin>>fetch;}using编译指令:其指令格局次要由using+namespace+名称空间名,它使得名称空间中的所有名称都能够应用,而不须要应用作用域解析运算符。 ...

September 16, 2022 · 1 min · jiezi

关于c:指针函数|函数指针|回调函数|指针数组|数组指针

指针函数指针函数,简略了解就是一个返回指针的函数,其本质是一个函数,而该函数的返回值是一个指针。申明格局如下: *类型标识符 函数名(参数表) 例如, int *myfun(int x,int y);留神:在函数名后面多了一个*号,而这个函数就是一个指针函数。其返回值是一个 int 类型的指针。 #include <iostream>using namespace std;#include<string.h>int *newAdd(int a, int b); // 申明指针函数int main() { int *p1 = NULL; p1 = newAdd(1, 2); printf("p1 = 0x%x \n", p1); printf("*p1 = %d \n", *p1); getchar(); return 0; }int *newAdd(int a, int b) { int *p = (int *)malloc(sizeof(int)); memset(p, 0, sizeof(int)); printf("函数内:p = 0x%x \n", p); *p = a + b; printf("函数内:*p = %d \n", *p); return p;}留神:在调用指针函数时,须要一个同类型的指针来接管其函数的返回值。 ...

September 11, 2022 · 2 min · jiezi

关于c++:C函数模板的具体化

在代码中申明函数模板的时候,是不会生成函数定义的,当编译器应用模板为特定类型生成函数定义时,失去的是模板实例。例如如下代码,这样的模板并非函数定义。 template<class T>void Swap(T &a, T &b){ T temp; temp = a; a = b; b = temp;}函数模板的具体化又分为隐式实例化、显示实例化、显示具体化。1、隐式实例化 int main(){ int a = 10, b = 20; Swap(a, b);}在上述代码中,函数调用Swap(i,j)导致编译器生成Swap实例,这种实例化称为隐式实例化,因为编译器之所以晓得须要进行定义,是因为程序调用了Swap函数时提供了int参数,这种实例化的形式存在效率低下的毛病,因为其无奈在程序编译时就生成函数定义。2、显示实例化显示实例化能够解决隐式实例化的毛病,其能够间接命令编译器创立特定的实例,其语法为如下template void Swap<int>(int, int);3、显示具体化显示具体化次要针对非凡的数据类型,如构造体,其能够对底层的模板进行改变,从而使其针对这种非凡的数据类型执行特定的操作。例如以下代码,我申明了一个构造体,想要只替换构造体中的salary和floor,不替换name,就要应用显示具体化。 struct job{ char name[40]; double salary; int floor;};template<> void Swap<job>(job&a, job&b){ double t1; int t2; t1 = a.salary; a.salary = b.salary; b.salary = t1; t2 = a.floor; a.floor = b.floor; b.floor = t2;}因而调用时,显示具体化将会优先于惯例模板。

September 10, 2022 · 1 min · jiezi

关于c:动态链接库如何函数寻址

原文地址:动态链接库如何函数寻址 最近咱们发现 go 编译为 so 之后,内存占用涨了好多,初步剖析下来,是动静符号导致的,感觉不太合乎常识趁着娃还在里面放假,正好学习学习~ hello worldint main() { printf("hello world\n")}在最简略的 hello world 中,printf 最终也是来自 libc.so 这个动态链接库通过 objdump,咱们能够找到这一行: 400638: call 400520 <printf@plt>这里的 printf@plt,示意 printf 这个函数是依赖的内部函数,是要动静寻址的。 为什么须要函数寻址不同于动态链接,函数地址在链接期(执行前),就能够确定下来了。然而,动态链接库的地址,是在程序执行的时候,加载 so 文件时能力确定的。那么,要调用动静库中的函数,是没有方法提前晓得的地址的,所以须要一套机制来寻找函数的地址。 具体而言,分为两种寻址: so 中导出的函数地址so 外部调用非导出的函数地址简而言之第一种,是通过函数名来寻址的,相当于在主程序里调用了 dlsym(x, "printf") 来寻址,而后 dlsym 会在 so 文件里找 printf 的地址第二种,是通过偏移量来寻址的,尽管相对地址不固定,然而 so 文件外部,两个函数之间的偏移量是固定的。 缓存减速通过字符串来查找,想想也晓得是比拟低效的,那有什么方法提速呢?原理也简略,就是加缓存。具体而言呢,是通过可执行文件中的两个段的配合,其中 .plt 可执行,.got.plt 可写,来实现缓存的成果。 还是从这一行 call 指令开始 400638: call 400520 <printf@plt>400520 来自 .plt 段,而且 .plt 是可执行的持续用 objdump 能够看指令: 400520: jmp QWORD PTR [rip+0x200afa] # 601020 <printf@GLIBC_2.2.5> 400526: push 0x0 40052b: jmp 400500 <.plt>这里有两个 jmp:第一个 jmp 的地址来自 601020,而这个 601020 来自 .got.plt 段,.got.plt 是可写的首次执行的时候,601020 里存的就是 400526,此时意味着慢门路,须要动静查找。当查到地址之后,会批改 601020 中的值,这样后续就能够间接一个 jmp 就实现寻址了,不须要再依照字符串查找了。 ...

September 6, 2022 · 1 min · jiezi

关于c#:winform数据导出CSV

winform数据导出CSV.csv是一种逗号分隔值文件格式,其文件以纯文本模式存储表格数据(数字和文本)。CSV文件由任意数目的记录组成,记录间以某种换行符分隔;每条记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符。通常,所有记录都有完全相同的字段序列。通常都是纯文本文件。/// <summary>/// 数据导出/// </summary>/// <param name="dataGridView"></param>/// <returns></returns>private bool dataGridViewToCSV(DataGridView dataGridView){ if(dataGridView.Rows.Count == 0) { MessageBox.Show("没有数据可导出!", "提醒", MessageBoxButtons.OK, MessageBoxIcon.Information); return false; } SaveFileDialog saveFileDialog = new SaveFileDialog(); saveFileDialog.Filter = "CSV files (*.csv)|*.csv"; saveFileDialog.FilterIndex = 0; saveFileDialog.RestoreDirectory = true; saveFileDialog.CreatePrompt = true; saveFileDialog.FileName = null; saveFileDialog.Title = "保留"; DateTime now = DateTime.Now; saveFileDialog.FileName = now.Year.ToString().PadLeft(2) + now.Month.ToString().PadLeft(2, '0') + now.Day.ToString().PadLeft(2, '0') + "-" + now.Hour.ToString().PadLeft(2, '0') + now.Minute.ToString().PadLeft(2, '0') + now.Second.ToString().PadLeft(2, '0'); if(saveFileDialog.ShowDialog() == DialogResult.OK) { Stream stream = saveFileDialog.OpenFile(); StreamWriter sw = new StreamWriter(stream, System.Text.Encoding.GetEncoding(-0)); string strLine = ""; try { //表头 for(int i = 0; i < dataGridView.ColumnCount; i++) { if(i > 0) strLine += ","; strLine += dataGridView.Columns[i].HeaderText; } strLine.Remove(strLine.Length - 1); sw.WriteLine(strLine); strLine = ""; //表的内容 for(int j = 0; j < dataGridView.Rows.Count; j++) { strLine = ""; int colCount = dataGridView.Columns.Count; for(int k = 0; k < colCount; k++) { if(k > 0 && k < colCount) strLine += ","; if(dataGridView.Rows[j].Cells[k].Value == null) strLine += ""; else { string cell = dataGridView.Rows[j].Cells[k].Value.ToString().Trim(); //避免外面含有特殊符号 cell = cell.Replace("\"", "\"\""); cell = "\"" + cell + "\""; strLine += cell; } } sw.WriteLine(strLine); } sw.Close(); stream.Close(); MessageBox.Show("数据被导出到:" + saveFileDialog.FileName.ToString(), "导出结束", MessageBoxButtons.OK, MessageBoxIcon.Information); } catch(Exception ex) { MessageBox.Show(ex.Message, "导出谬误", MessageBoxButtons.OK, MessageBoxIcon.Information); return false; } } return true;}

September 5, 2022 · 1 min · jiezi

关于c#:dataGridView读写文本

dataGridViewDataGridView控件是数据表格控件,属于很罕用的控件。 winform DataGridView 属性阐明① 获得或者批改以后单元格的内容 ② 设定单元格只读 ③ 不显示最上面的新行 ④ 判断新增行 ⑤ 行的用户删除操作的自定义 ⑥ 行、列的暗藏和删除 ⑦ 禁止列或者行的Resize ⑧ 列宽和行高以及列头的高度和行头的宽度的主动调整 ⑨ 解冻列或行 ⑩ 列程序的调整 ⑪ 行头列头的单元格⑫ 剪切板的操作 ⑬ 单元格的ToolTip的设置 ⑭ 右键菜单(ContextMenuStrip)的设置 ⑮ 单元格的边框、 网格线款式的设定 ⑯ 单元格示意值的设定 ⑰ 用户输出时,单元格输出值的设定 ⑱ 设定新加行的默认值 constant con = new constant();//读取private void loadlistbox2(){ dataGridView1.ColumnCount = 1; string z; if(File.Exists(".//allitems.txt")) { FileStream fs = new FileStream(".//allitems.txt", System.IO.FileMode.Open, System.IO.FileAccess.Read); StreamReader sr = new StreamReader(fs, System.Text.Encoding.GetEncoding("utf-8")); try { while(true) { z = sr.ReadLine(); if(z == null) break; dataGridView1.Rows.Add(z); } } finally { sr.Close(); fs.Dispose(); fs.Close(); } }}string st = "";//写入private void savetestitem(){ // dataGridView1.ColumnCount = 1; if(File.Exists(".//allitems.txt")) { FileStream fs = new FileStream(".//allitems.txt", System.IO.FileMode.Open, System.IO.FileAccess.Write); StreamWriter sr = new StreamWriter(fs, System.Text.Encoding.GetEncoding("utf-8")); try { for(int i = 0; i < 22; i++) { for(int j = 0; j < 1; j++) { st = st + dataGridView1.Rows[i].Cells[j].Value; } sr.WriteLine(st); st = ""; //for (int i = 0; i < dataGridView1.Rows.Count; i++) //{ // sr.WriteLine(dataGridView1.Rows[i].Cells); // } } } finally { sr.Close(); fs.Dispose(); fs.Close(); } }}

September 5, 2022 · 1 min · jiezi

关于c++:c-value-category

微软官网解释 示例 glvalueg是generalize的意思,glvalue是个形象的概念,是lvalue和xvalue的并集 lvalue左值字面意思是能够放在右边的值,包含成员变量和能返回一个左值的函数 int main(){ int i, j, *p; // Correct usage: the variable i is an lvalue and the literal 7 is a prvalue. i = 7; // Incorrect usage: The left operand must be an lvalue (C2106).`j * 4` is a prvalue. 7 = i; // C2106 j * 4 = 7; // C2106 // Correct usage: the dereferenced pointer is an lvalue. *p = i; // Correct usage: the conditional operator returns an lvalue. ((i < 3) ? i : j) = 7; // Incorrect usage: the constant ci is a non-modifiable lvalue (C3892). const int ci = 7; ci = 9; // C3892}xvaluex是expiring,xvalue意思是行将走完生命周期的值,xvalue有地址但程序无奈进入,例如函数返回右值援用的表达式,或者应用move语句这类传入的参数,这种参数快死掉了,就叫做xvalue,例如1 + 1, move(a), static_cast<>({xvalue}) ...

September 4, 2022 · 1 min · jiezi

关于c++:OneFlow源码阅读7静态图与运行时

oneflow动态图的训练效率远高于动态图(eager模式)。本文试图通过一个简略例子,联合0.8.0的代码,看一下动态图和运行时的实现机制。在开始之前,倡议先读一下参考资料中《OneFlow框架的零碎设计》等系列文章。对动态图、运行时的基本概念和设计理念有根本的理解,会更容易了解代码。 1 代码示例上面的示例代码来自官网文档,是一个线性模型的前向计算。后续次要基于这段代码进行剖析。 import oneflow as flowimport oneflow.nn as nnclass ModuleMyLinear(nn.Module): def __init__(self, in_features, out_features): super().__init__() self.weight = nn.Parameter(flow.randn(in_features, out_features)) self.bias = nn.Parameter(flow.randn(out_features)) def forward(self, input): return flow.matmul(input, self.weight) + self.biaslinear_model = ModuleMyLinear(4, 3)class GraphMyLinear(nn.Graph): def __init__(self): super().__init__() # ModuleBlock self.model = linear_model def build(self, input): # ModuleBlock.__call__ return self.model(input)graph_mylinear = GraphMyLinear()input = flow.randn(1, 4)out = graph_mylinear(input)print(out)2 oneflow包的初始化import oneflow在初始化包时,与动态图相干的次要操作如下: GetEnv EnvGlobalObjectsScope::Init 启动各个节点的管制面网络连接初始化VM启动各个节点的数据面网络连接初始化KernelObserverNewDefaultSession RegsiterSession 创立 Session,并注册为 default session创立 Python MultiClientSession 并保留到dict,但并不 TryInit ...

September 2, 2022 · 3 min · jiezi

关于c#:NPinyin-不支持中英混合转换怎么破

最近在我的项目中用到汉字转拼音的需要,用的是 NPinyin 来实现的,然而在应用的过程中呈现了与预期不符的状况。 咱们先来看看失常应用: string str = NPinyin.Pinyin.GetPinyin("小黄本黄");Console.WriteLine(str);输入为 xiao huang ben huang显然,这是合乎预期的,但如果咱们在调用这个转换方法前,不晓得以后字符串是中文还是拼音,那咱们预期是不是会冀望对拼音局部不做扭转呢?但实际上不是的: string str = NPinyin.Pinyin.GetPinyin("xiao huang ben huang");Console.WriteLine(str);输入为 x i a o h u a n g b e n h u a n g它对每个英文字符也做了转换,导致每个字符前面多出了一个空格。 如果咱们做以下调整,就能够返回咱们预期的后果啦 public static string GetPinyin(string str){ StringBuilder sb = new StringBuilder(); for (int i = 0; i < str.Length; i++) { if (str[i] > 127) { string pinyin = Pinyin.GetPinyin(str[i]); sb.Append(pinyin); // 如果是最初一位,就不必追加空格 if (i == str.Length - 1) continue; // 如果不是最初一位,但下一位是符号,也不必追加空格 if (char.IsPunctuation(str[i+1])) continue; sb.Append(" "); continue; } sb.Append(str[i]); } return sb.ToString();}咱们测试一下 ...

August 31, 2022 · 1 min · jiezi

关于c++:Brpc-服务端收包源码分析一

大家好,我是dandyhuang,brpc在c艹届还是比拟牛逼的rpc框架,本次带来brpc的server端的源码剖析。剖析源码前,大家先搭建好环境,有利于代码调试和了解。依照brpc框架中example的echo_c++为例子,并且将protobuf中,编译出的两头文件echo.pb.cc和.h保留,有利于咱们更好的代码了解。 server端应用namespace example {class EchoServiceImpl : public EchoService {public: EchoServiceImpl() {}; virtual ~EchoServiceImpl() {}; virtual void Echo(google::protobuf::RpcController* cntl_base, const EchoRequest* request, EchoResponse* response, google::protobuf::Closure* done) { brpc::ClosureGuard done_guard(done); brpc::Controller* cntl = static_cast<brpc::Controller*>(cntl_base); response->set_message(request->message()); if (FLAGS_echo_attachment) { cntl->response_attachment().append(cntl->request_attachment()); } }};int main(int argc, char* argv[]) { // Parse gflags. We recommend you to use gflags as well. GFLAGS_NS::ParseCommandLineFlags(&argc, &argv, true); brpc::Server server; // 继承proto文件 example::EchoServiceImpl echo_service_impl; if (server.AddService(&echo_service_impl, brpc::SERVER_DOESNT_OWN_SERVICE) != 0) { LOG(ERROR) << "Fail to add service"; return -1; } butil::EndPoint point; point = butil::EndPoint(butil::IP_ANY, FLAGS_port); // Start the server. brpc::ServerOptions options; options.idle_timeout_sec = FLAGS_idle_timeout_s; if (server.Start(point, &options) != 0) { LOG(ERROR) << "Fail to start EchoServer"; return -1; } // Wait until Ctrl-C is pressed, then Stop() and Join() the server. server.RunUntilAskedToQuit(); return 0;}总体代码还是比拟简洁,如果可能依据IDL主动代码生成那样就更完满了。话不多说,间接开撸源码 ...

August 31, 2022 · 17 min · jiezi

关于c++:类应用队列模拟

背景:Heather银行打算在Food Heap超市开设一个ATM。Food Heap超市的管理者放心排队期待应用ATM的人流会烦扰超市的交通,心愿限度排队期待的人数。Heather银行心愿对顾客排队等待时间进行估测。 工作:自行设计一个队列的类和顾客的类,顾客达到的工夫随机,并且编写一个程序来模仿顾客和队列的交互。 思路:首先设计队列类,队列是一个尾进头出的构造,若采纳数组来示意队列,删除队列头部元素,须要将整体的元素往前挪动一格,操作较为繁琐,应用链表的数据结构来示意队列,删除队列首元素时,只需针对单个元素,减少队列元素时,只须要扭转地址。链表与数组相比,链表查找元素较为麻烦,增减元素较为不便。 队列类的设计1、首先设计类的私有接口 队列所能包容的项目数应该要有限度,因而应该在类中设计一个const属性来存储队列所能存储的最大数目。队列可能创立空队列,所以在队列类的构造函数中该当设置初始化属性的参数可能查看队列是否为满,所以应该设置一个bool函数,还想到要有一个类中现有的items的属性,通过这个items的大小与最大数目来进行比拟从而判断队列是否为满查看队列是否为空,与队列是否为满相相似。须要一个函数成员可能返回以后队列中的数目(重点)须要一个插入队列的成员函数和删除队列成员的成员函数,波及到链表的删除和增加,因而在类中应该各设置一个指向头部和指向尾部的指针。class Quene{public: Quene(int qs); ~Quene(); bool isempty() const; bool isfull() const; int countQuene() const; bool enquene(const Item& item); bool dequene(Item item);2、类的公有局部申明除上述提到的公有局部以外,针对链表数据结构,应该设计一个结点构造,结点构造蕴含数值和指向下一个结点的地址。 struct Node{ Item item; Node* next;}class Quene{public: Node* first; Node* rear; int items; const int Maxitems;上述代码引出一个问题:是应该在类中申明构造体,还是在全局中进行申明。全局中进行申明的话,作用域为整个文件,若其余头文件也申明了这个结点定义,当一起蕴含时,容易呈现抵触。若在类中申明构造,则其作用域为类,则不必放心抵触问题。若申明在公有局部,则只能类内进行应用,若在私有局部申明,要在类外应用,只需Quene::Node。 最初队列的类私有成员和公有成员申明: class Quene{private: struct Node { Item item; Node* next; } Node* first; Node* rear; int items; const int Maxitems;public: Quene(int qs); ~Quene(); bool isempty() const; bool isfull() const; int countQuene() const; bool enquene(const Item& item); bool dequene(Item item);3、类的实现 ...

August 30, 2022 · 3 min · jiezi

关于c#:重温-C-Lambda-表达式

尽管从事 .Net 开发有较长一段时间了,但对一些基础知识把握得不是很好,近期换了工作了,看到代码中的一些 Action 和 Func<> 的用法,于是来补一下根底。 首先说一下几个规定,就能很好了解了: Lambda 运算符,=> 读做 "goes to"=> 左侧为参数,右侧为表达式或语句块,如 (a,b) => a+b,示意 a,b 为入参,返回值为 a+b=> 左边有 {} 时,为语句块,无 {} 时,为表达式Action 无返回值,Func<> 有返回值;即 Action<in T1,in T2> 中,T1 和 T2 都为入参,而 Func<in T1,in T2,out T3> 中,T1 和 T2 为入参,T3 为返回值(最初一个为返回值)。咱们举个例子吧 表达式// return min valueFunc<int,int,int> Min = (a,b) => a < b ? a : b;int x = Min(1,2);Console.WriteLine(x);// 1语句块Func<int,int,int> Min = (a,b) =>{ if (a < b) return a; return b;};int x = Min(1,2);Console.WriteLine(x);// 1再举一个 Action 的例子吧 ...

August 28, 2022 · 1 min · jiezi

关于c++:c-单例模式

// 探索单例模式以及单例模式的线程平安问题// meyer's singleton// 懒汉模式的最优雅版本class singleton{private: singleton(/* args */); ~singleton(); singleton(const singleton &); singleton operator=(const singleton &);public: static singleton &getInstance() { static singleton instance; return instance; }};

August 27, 2022 · 1 min · jiezi

关于c#:反射

public static T DeepCopyByReflect<T>(T obj) { //如果是字符串或值类型则间接返回 if (obj is string || obj.GetType().IsValueType) return obj; object retval = Activator.CreateInstance(obj.GetType()); FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static); foreach (FieldInfo field in fields) { try { field.SetValue(retval, DeepCopyByReflect(field.GetValue(obj))); } catch { } } return (T)retval; }

August 26, 2022 · 1 min · jiezi

关于c:记录一次C语言调用go生成的动态库的踩坑过程

记录一次C语言调用go生成的动静库的踩坑过程问题景象因为某些非凡起因,须要在C语言中调用go语言生成的so,原本挺顺利,所有都运行的很好。忽然某一天,不晓得怎么回事,再一个新程序中无奈失常运行了,看到的景象是程序无任何响应,相似于间接卡死了。应用gdb查看过程以后的信息,看到如下调用栈: (gdb) source /root/go/src/runtime/runtime-gdb.pyLoading Go Runtime support.(gdb) bt#0 runtime.futex () at /usr/local/go/src/runtime/sys_linux_amd64.s:520#1 0x00007fff23c550f6 in runtime.futexsleep (addr=0xfffffffffffffe00, val=0, ns=140733793710979) at /usr/local/go/src/runtime/os_linux.go:44#2 0x00007fff23c35667 in runtime.notetsleep_internal (n=0x7fff23dc66e8 <runtime.work+232>, ns=-1) at /usr/local/go/src/runtime/lock_futex.go:183#3 0x00007fff23c35785 in runtime.notetsleepg (n=0x7fff23dc66e8 <runtime.work+232>, ns=-1) at /usr/local/go/src/runtime/lock_futex.go:237#4 0x00007fff23c41338 in runtime.gcBgMarkStartWorkers () at /usr/local/go/src/runtime/mgc.go:1126#5 0x00007fff23c3fd92 in runtime.gcStart (trigger=...) at /usr/local/go/src/runtime/mgc.go:637#6 0x00007fff23c36e3d in runtime.mallocgc (size=565248, typ=0x7fff23cfd160, needzero=true) at /usr/local/go/src/runtime/malloc.go:1174#7 0x00007fff23c6dfaa in runtime.growslice (et=, old=..., cap=) at /usr/local/go/src/runtime/slice.go:267#8 0x00007fff23c918ef in regexp/syntax.(*compiler).inst (c=0xc000044bf8, op=) at /usr/local/go/src/regexp/syntax/compile.go:164#9 regexp/syntax.(*compiler).rune (c=0xc000044bf8, r=[]int32 = {...}, flags=212) at /usr/local/go/src/regexp/syntax/compile.go:273#10 0x00007fff23c90f1e in regexp/syntax.(*compiler).compile (c=0xc000044bf8, re=0xc000190000) at /usr/local/go/src/regexp/syntax/compile.go:101#11 0x00007fff23c8f805 in regexp/syntax.Compile (re=0xc000190000) at /usr/local/go/src/regexp/syntax/compile.go:74#12 0x00007fff23ca4a9a in regexp.compile (expr=,mode=, longest=false) at /usr/local/go/src/regexp/regexp.go:178#13 0x00007fff23ca5591 in regexp.Compile (expr="") at /usr/local/go/src/regexp/regexp.go:133#14 regexp.MustCompile (str="") at /usr/local/go/src/regexp/regexp.go:309#15 0x00007fff23ca8e0a in main.CheckPostAddress (buf=, bufLen=) at /root/codes/di_rechk/rechk.go:540#16 0x00007fff23ca9a88 in _cgoexp_67df0785bef2_CheckPostAddress (a=0x7fffffffc740) at _cgo_gotypes.go:162#17 0x00007fff23c2e21a in runtime.cgocallbackg1 (fn=0x7fff23ca9a60 <_cgoexp_67df0785bef2_CheckPostAddress>, frame=0x7fffffffc740, ctxt=0)at /usr/local/go/src/runtime/cgocall.go:306#18 0x00007fff23c2dee9 in runtime.cgocallbackg (fn=0x7fff23ca9a60 <_cgoexp_67df0785bef2_CheckPostAddress>, frame=0x7fffffffc740, ctxt=0)at /usr/local/go/src/runtime/cgocall.go:232#19 0x00007fff23c83791 in runtime.cgocallbackg (fn=0x7fff23ca9a60 <_cgoexp_67df0785bef2_CheckPostAddress>, frame=0x7fffffffc740, ctxt=0)at :1#20 0x00007fff23c813f3 in runtime.cgocallback () at /usr/local/go/src/runtime/asm_amd64.s:915#21 0x00007fff23c81601 in runtime.goexit () at /usr/local/go/src/runtime/asm_amd64.s:1581#22 0x0000000000000000 in ?? ()(gdb) info goroutines 17 syscall runtime.notetsleepg 2 waiting runtime.gopark 3 waiting runtime.gopark 4 waiting runtime.gopark 19 runnable runtime.gcBgMarkWorker(gdb) goroutine 17 bt#0 runtime.notetsleepg (n=0x7fff23dc66e8 <runtime.work+232>, ns=-1) at /usr/local/go/src/runtime/lock_futex.go:237#1 0x00007fff23c41338 in runtime.gcBgMarkStartWorkers () at /usr/local/go/src/runtime/mgc.go:1126#2 0x00007fff23c3fd92 in runtime.gcStart (trigger=...) at /usr/local/go/src/runtime/mgc.go:637#3 0x00007fff23c36e3d in runtime.mallocgc (size=565248, typ=0x7fff23cfd160, needzero=true) at /usr/local/go/src/runtime/malloc.go:1174#4 0x00007fff23c6dfaa in runtime.growslice (et=, old=..., cap=) at /usr/local/go/src/runtime/slice.go:267#5 0x00007fff23c918ef in regexp/syntax.(*compiler).inst (c=0xc000044bf8, op=) at /usr/local/go/src/regexp/syntax/compile.go:164#6 regexp/syntax.(*compiler).rune (c=0xc000044bf8, r=[]int32 = {...}, flags=212) at /usr/local/go/src/regexp/syntax/compile.go:273#7 0x00007fff23c90f1e in regexp/syntax.(*compiler).compile (c=0xc000044bf8, re=0xc00022a000) at /usr/local/go/src/regexp/syntax/compile.go:101#8 0x00007fff23c8f805 in regexp/syntax.Compile (re=0xc00022a000) at /usr/local/go/src/regexp/syntax/compile.go:74#9 0x00007fff23ca4a9a in regexp.compile (expr=,mode=, longest=false) at /usr/local/go/src/regexp/regexp.go:178#10 0x00007fff23ca5591 in regexp.Compile (expr=""") at /usr/local/go/src/regexp/regexp.go:133#11 regexp.MustCompile (str=""") at /usr/local/go/src/regexp/regexp.go:309#12 0x00007fff23ca8e0a in main.CheckPostAddress (buf=, bufLen=) at /root/codes/di_rechk/rechk.go:540#13 0x00007fff23ca9a88 in _cgoexp_67df0785bef2_CheckPostAddress (a=0x7fffffffc740) at _cgo_gotypes.go:162#14 0x00007fff23c2e21a in runtime.cgocallbackg1 (fn=0x7fff23ca9a60 <_cgoexp_67df0785bef2_CheckPostAddress>, frame=0x7fffffffc740, ctxt=0)at /usr/local/go/src/runtime/cgocall.go:306#15 0x00007fff23c2dee9 in runtime.cgocallbackg (fn=0x7fff23ca9a60 <_cgoexp_67df0785bef2_CheckPostAddress>, frame=0x7fffffffc740, ctxt=0)at /usr/local/go/src/runtime/cgocall.go:232#16 0x00007fff23c83791 in runtime.cgocallbackg (fn=0x7fff23ca9a60 <_cgoexp_67df0785bef2_CheckPostAddress>, frame=0x7fffffffc740, ctxt=0)at :1#17 0x00007fff23c813f3 in runtime.cgocallback () at /usr/local/go/src/runtime/asm_amd64.s:915#18 0x00007fff23c81601 in runtime.goexit () at /usr/local/go/src/runtime/asm_amd64.s:1581#19 0x0000000000000000 in ?? ()(gdb) goroutine 2 bt#0 runtime.gopark (unlockf=, lock=, reason=, traceEv=, traceskip=)at /usr/local/go/src/runtime/proc.go:367#1 0x00007fff23c5b86d in runtime.goparkunlock (reason=, traceEv=, traceskip=, lock=)at /usr/local/go/src/runtime/proc.go:372#2 runtime.forcegchelper () at /usr/local/go/src/runtime/proc.go:306#3 0x00007fff23c81601 in runtime.goexit () at /usr/local/go/src/runtime/asm_amd64.s:1581#4 0x0000000000000000 in ?? ()(gdb) goroutine 3 bt#0 runtime.gopark (unlockf=, lock=, reason=, traceEv=, traceskip=)at /usr/local/go/src/runtime/proc.go:367#1 0x00007fff23c48ee8 in runtime.goparkunlock (reason=, traceEv=, traceskip=, lock=)at /usr/local/go/src/runtime/proc.go:372#2 runtime.bgsweep () at /usr/local/go/src/runtime/mgcsweep.go:163#3 0x00007fff23c81601 in runtime.goexit () at /usr/local/go/src/runtime/asm_amd64.s:1581#4 0x0000000000000000 in ?? ()(gdb) goroutine 4 bt#0 runtime.gopark (unlockf=, lock=, reason=, traceEv=, traceskip=)at /usr/local/go/src/runtime/proc.go:367#1 0x00007fff23c46fed in runtime.goparkunlock (reason=, traceEv=, traceskip=, lock=)at /usr/local/go/src/runtime/proc.go:372#2 runtime.bgscavenge () at /usr/local/go/src/runtime/mgcscavenge.go:265#3 0x00007fff23c81601 in runtime.goexit () at /usr/local/go/src/runtime/asm_amd64.s:1581#4 0x0000000000000000 in ?? ()(gdb) goroutine 19 bt#0 runtime.gcBgMarkWorker () at /usr/local/go/src/runtime/mgc.go:1166#1 0x00007fff23c81601 in runtime.goexit () at /usr/local/go/src/runtime/asm_amd64.s:1581#2 0x0000000000000000 in ?? ()(gdb) info threadsId Target Id Frame1 Thread 0x7ffff7966b80 (LWP 2024707) "nginx" runtime.futex () at /usr/local/go/src/runtime/sys_linux_amd64.s:5202 Thread 0x7ffef1ffb700 (LWP 2024717) "nginx" 0x00007ffff7a483bf in __GI___clock_nanosleep (clock_id=clock_id@entry=0, flags=flags@entry=0, req=req@entry=0x7ffef1ffae80, rem=rem@entry=0x0) at ../sysdeps/unix/sysv/linux/clock_nanosleep.c:783 Thread 0x7ffef27fc700 (LWP 2024718) "ZMQbg/Reaper" 0x00007ffff7a8a5ce in epoll_wait (epfd=42, events=events@entry=0x7ffef27fb200, maxevents=maxevents@entry=256, timeout=timeout@entry=-1) at ../sysdeps/unix/sysv/linux/epoll_wait.c:304 Thread 0x7ffef2ffd700 (LWP 2024719) "ZMQbg/IO/0" 0x00007ffff7a8a5ce in epoll_wait (epfd=44, events=events@entry=0x7ffef2ffc200, maxevents=maxevents@entry=256, timeout=timeout@entry=-1) at ../sysdeps/unix/sysv/linux/epoll_wait.c:30问题解决过程因为对go不太熟悉,所以不晓得出了什么问题。go自身的代码也比较简单,没有太简单的操作。而且之前的程序调用这些go代码生成的so,也能整成运行。从网上查资料也是一头雾水,不晓得该怎么查。通过一段时间的搜寻,终于在stackoverflow中看到了一个相似问题。依照这个起因进行批改,果然批改好了。 ...

August 24, 2022 · 3 min · jiezi

关于c:C语言中文网课后作业day01

一、第一天1、C 语言能够用来开发网站吗?C语言只能做一些简略的事件,不适宜用来开发网站。 2、很多人认为“当程序员像农民一样苦逼”,对此你是怎么认为的?是一种自我讥嘲 3、就编程而言,可移植性意味着什么?一次编码,多平台运行,不必思考多平台硬件差别,更注程序自身的逻辑。 4、二进制、八进制、十进制、十六进制的前缀是什么?二进制:0b八进制:0十进制:失常数字十六进制:0x 5、二进制 1011 1101 转换为十六进制是多少?转10进制:11 13转16进制:b d后果为:0xbd 6、十进制 89 转换为二进制是多少?先将二进制位数对应到10进制数值,再拼凑起来 64 32 16 8 4 2 1 1 0 1 1 0 0 1后果为:1011001 7、0x7D 转换为十进制是多少?112(7*16) + 13 = 125 8、 076 转换为十进制是多少?后果为:62 9、二进制 101 110 转换为八进制是多少?后果为:56

August 20, 2022 · 1 min · jiezi

关于c:C语言级联内存池之轻松零拷贝IPC

让程序轻松逾越堆与共享内存的阻碍,轻松实现零拷贝IPC 什么是级联内存池?如何让程序轻松逾越堆与共享内存的阻碍?如何轻松实现零拷贝IPC?本文给你带来不一样的程序设计视线 以前的文章中,码哥介绍过利用内存池有哪些长处,咱们列举如下: 集中开释,便于编码逻辑,集中开释缩小空洞特定的调配开释算法及池构造,能够借助指令预取及cache命中来晋升性能提早开释闲置内存块,通过晋升复用率来晋升调配效率因而,本文不再赘述下面的局部。 这篇文章咱们介绍一种级联构造内存池,该内存池的实现能够参考:Github: Melon库 池构造的模型大抵如下: ------------- | 父池 | ------------- | | ----------- --------- | 子池1 | | 子池2 | ----------- --------- | | .... -------- -------- | 孙池1 | | 孙池2 | -------- --------这种构造是什么意思呢? 子池所应用的内存及其所能调配的内存均来自于父池。故此,孙池的内存也是由其依赖的子池而来的。 在Melon库的内存池组件中,内存的起源有三处: 堆内存(或者匿名映射区),即malloc库所提供共享内存(次要是用于奴才过程间的共享,因而是mmap的匿名映射区共享)其余内存池治理的内存咱们先来看一个简略的内存池应用的例子: 示例一,Melon惯例内存池应用举例#include <stdio.h>#include <stdlib.h>#include "mln_core.h"#include "mln_log.h"#include "mln_alloc.h"int main(int argc, char *argv[]){ char *p; mln_alloc_t *pool; struct mln_core_attr cattr; /* libmelon init begin*/ cattr.argc = argc; cattr.argv = argv; cattr.global_init = NULL; cattr.master_process = NULL; cattr.worker_process = NULL; if (mln_core_init(&cattr) < 0) { fprintf(stderr, "init failed\n"); return -1; } /* libmelon init end */ pool = mln_alloc_init(NULL); if (pool == NULL) { mln_log(error, "pool init failed\n"); return -1; } p = (char *)mln_alloc_m(pool, 6); if (p == NULL) { mln_log(error, "alloc failed\n"); return -1; } memcpy(p, "hello", 5); p[5] = 0; mln_log(debug, "%s\n", p); mln_alloc_destroy(pool); return 0;}在这个例子中,咱们创立了一个堆内存池,并且利用该内存池调配了6个字节的内存区用于写入"hello"字符串。 ...

August 20, 2022 · 2 min · jiezi

关于c++:ABAQUS-稳态动力学求解纯理论公式

本文用于阐明:abaqus谐响应分析的模态叠加原理,大部分来自abaqus Document的theory 局部。具体公式推导的过程要查《构造动力学》0. 总括基于模态的谐响应分析,能够通过扫频的形式求解频率范畴内构造的线性稳态响应状况。阻尼是和频率相干的,但模态叠加法只须要晓得n个模态阻尼即可推广到其余频率范畴(起因详见文内公式)。 1. 谐响应分析的目标用来求解构造在间断谐波激励下的线性响应.求解稳态动力学响应有三种办法:subspace,direct,modal。base modal的办法是利用前一个剖析步提取进去的一系列模态特色计算稳态解。 2. ABAQUS的求解原理2.1 特征值提取对于一个具备N个自由度的多自由度零碎,可用N个独立的广义坐标形容零碎的静止状态: $$a^{N\times1}=\{a_1,a_2,a_3,...,a_N\}^{T}$$ 对于N自由度的零碎,肯定能够找到N个固有频率\( w_{\alpha} \)以及绝对应的振型\( \phi_{\alpha}^{N\times1} \)【\( \alpha=1...n,n是提取的模态的数目 \)】 。\( \phi^{N} \)右边的矩阵是\( M\times N \)的,等号左边是0,所以\( \phi^{N} \)是\( N\times 1 \)的。 所谓振型按我的了解就是共振时,构造的一个形态。用数学形式示意就是一个特定的解向量\( \phi_{\alpha}^{N} \)将\( \phi_{\alpha}^{N\times 1} \)组装成 \( Nxn \)矩阵\( \Phi \),其中每一列都蕴含一个特色模态。 2.2 模态叠加有阻尼的构造动力学方程: 模态叠加用矩阵模式写为 $$u^{N\times1}=\Phi^{N\times n} q^{n\times 1}$$ 列矢量\( q \)——模态自由度(待求)在静止方程中插入模态叠加表达式,代入动力学方程: $$M\Phi \ddot{q}+C\Phi \dot{q}+K\Phi q=f(t)^{N \times1}$$ 左乘\( \Phi^{T} \)后失去: $$\Phi^{T}M\Phi \ddot{q}+\Phi^{T}C\Phi \dot{q}+\Phi^{T}K\Phi q=\Phi^{T}f(t)^{N\times 1}$$ 此时,原方程组现已从求解 N 个变量简化为 n 个变量,右侧\( \Phi^{T}f(t)^{N\times 1} \) 为模态载荷,是外载荷在每个特色模态上的投影。 ...

August 18, 2022 · 2 min · jiezi

关于c++:数据缓冲区

\r 和 \n 的区别\r 示意回车 (回车示意换到以后行的最开始)\n 示意换行(换行只是换到下一行)留神:然而在理论应用时,\n 就间接示意了 \r\n 回车换行。缓冲区的概念行缓冲:常见的是对显示器进行刷新数据时 即必须缓冲区中一行填满了或者遇到 \n 才会输入到显示器全缓冲:对文件进行写入时采纳全缓冲 行将整个缓冲区填满才会刷新到磁盘中。无缓冲:即刷新数据时没有缓冲区。行缓冲示例一:下列代码执行后的后果是:进行5秒后才显示 hello world printf 这行代码是先执行的然而 printf 中没有 \n ,并且缓冲区中的一行并没有填满,所以没有输入到显示器所以继续执行上面的 sleep 代码在程序完结后会刷新缓冲区,将缓冲区的内容输入到显示器,所以最初依然会显示。void test(){ printf("hello world"); //退出 \n 后就会立刻输入到显示器了。 sleep(5); }行缓冲示例二下列代码显示后果为:倒计时,并且下一次的数字会笼罩上一次的数字。因为 \r 只是回车,并未换行,所以仍然会在之前那一行持续输入并且回车后,会回到这一行的起始地位,所以笼罩了上一次的值。#include <unistd.h>void test(){ int i = 10; while(i) { printf("%2d\r",i); //%2d 示意显示两个字符 fflush(stdout); //fflush是一个库函数,用来立刻刷新缓冲区输入到显示器中 sleep(1); i--; } }全缓冲与无缓冲示例一#include <stdio.h>#include <unistd.h>#include <string.h>int main(){ //C语言函数 printf("hello printf\n"); fprintf(stdout,"hello fprintf\n"); //零碎函数 const char * msg = "hello write\n"; write(1,msg,strlen(msg)); fork(); return 0;} ...

August 18, 2022 · 1 min · jiezi

关于c++:ROS教程Xavier

原文链接 1.设置当前工作空间source devel/setup.bash2.catkin_make程序修改,须要首先运行: catkin_make而后运行roslaunch: roslaunch stixel_ros_cc stixeltest.launch3.rviz的应用新开一个终端运行: rviz   学习更多编程常识,请关注我的公众号: 代码的路

August 18, 2022 · 1 min · jiezi

关于c:未来源码丨会写代码的AI开源了C语言写得比Codex还要好掌握12种编程语言丨CMU

举荐语: 近期,代码的大型语言模型 (LM)在实现代码和从自然语言形容合成代码方面显示出微小的后劲。然而,以后最先进的代码 LM(例如 Codex (Chen et al., 2021))尚未公开,留下了许多对于其模型和数据设计决策的问题。援用咱们的指标是通过对各种编程语言中最大的现有模型的零碎评估来填补其中的一些空白:Codex、GPT-J、GPT-Neo、GPT-NeoX-20B 和 CodeParrot。只管 Codex 自身不是开源的,但咱们发现,针对自然语言建模,现有的开源模型的确在某些编程语言中获得了靠近的后果。咱们进一步确定了一个重要的缺失局部,即专门在多语言代码语料库上训练的大型开源模型。咱们公布了一个新模型 PolyCoder,它具备基于 GPT-2 架构的 2.7B 参数,该模型在单台机器上应用 12 种编程语言的 249GB 代码进行了训练。在 C 编程语言中,PolyCoder 优于包含 Codex 在内的所有模型。咱们训练有素的模型是开源的,可在此 https URL 上公开取得,这使得该畛域的将来钻研和利用成为可能。援用—— MobTech袤博科技资深java开发工程师 零零发 MobTech袤博 比Codex还会写C语言的AI代码生成模型,当初开源了!这段时间,用AI写代码能够说是大火,其中最驰名的要属OpenAI的Codex和DeepMind的AlphaCode。 然而,这两个AI模型,全都没有开源: 其中AlphaCode只给出了一些测试样例,而Codex只凋谢了API。 为此,来自CMU的几个钻研人员,用GPT-2搞出了一个名叫PolyCoder的AI代码生成模型,而且还是开源的。 据钻研人员示意,尽管PolyCoder最大只有27亿参数(相比Codex有120亿参数),但它用C语言写进去的代码,比Codex的成果还要好。 这外面到底有什么秘诀? 用12种编程语言代码集训练首先来看训练用的数据集,这也是PolyCoder的最大特点之一。 此前,包含Codex、CodeParrot等AI代码生成模型,次要都是基于Python语言的代码来训练。 例如Codex的评估数据集之一HumanEval,评估的也是生成Python代码的成果。相比之下,PolyCoder采纳了多种编程语言代码集来训练,一共有12种:C、C#、C++、Go、Java、JavaScript、PHP、Python、Ruby、Rust、Scala和TypeScript。 其中,C语言的代码量是最多的,达到了221GB;而Python代码的数据量比Codex和CodeParrot用得都要少。 这里PolyCoder用的是GitHub上的公开代码,次要选取的是各种编程语言中比拟受欢迎的库,每个库至多有50 Stars。 据钻研人员示意,每种编程语言库的Stars总数加起来不超过25k,以防止模型生成的代码成果太过于歪斜最风行的编程语言(通常编程语言越风行,库的Stars就越多)。 通过提取库中的文件、通过简略解决(包含打消反复代码)后,一共筛选出大概254GB的数据用于训练。 而后是预训练的办法。 语言模型的预训练方法通常有三种。第一种是自左向右的语言模型,依据上文预测下文,比拟实用于代码生成等;第二种是掩蔽语言模型,基于上下文预测屏蔽片段,比拟适宜代码分类等;第三种是编解码器模型,比拟实用于代码正文等工作。 这里PolyCoder次要采纳的是第一种预训练方法。 相比于同样采纳GPT-2训练的CodeParrot和Codex,PolyCoder在超参数设置上也略微有一些差别:PolyCoder一共提供了三种不同的模型,别离有27亿参数、4亿参数和1.6亿参数,钻研人员能够依据本身需要和不同的训练能力来选取适合的模型。那么,最终训练进去的AI模型,代码生成成果如何? C语言写得尤其好,但Python不行钻研人员将PolyCoder与已有的AI代码生成模型进行了比照。因为AlphaCode不好比拟(接口没凋谢),所以钻研人员次要剖析了上面这些模型,包含GPT-Neo、CodeParrot和Codex等。其中蓝色的是开源的,橙色的是没开源的:从参数量来看,PolyCoder并不是最顶尖的,最大的27亿参数模型也只有Codex的四分之一不到。钻研人员先是用语言模型评估罕用的困惑度对一系列模型进行了比拟。 困惑度(Perplexity),用于掂量语言模型(LM)的好坏。困惑度越低,语言模型面对代码感到困惑的水平就越低,模型生成成果越好。从图中来看,PolyCoder在C语言中意外获得了最好的成果(困惑度最低)。用大量C语言训练PolyCoder的后果阐明,即便模型整体原理不变(基于GPT-2),单纯扭转训练用的代码集,也能训练出善于不同语言格调的AI代码生成模型。 惋惜的是,从其余语言来看,生成的成果就齐全没方法和Codex相比了:例如,在次要用于评估Python代码的HumanEval上,PolyCoder的能力远不如Codex好:据论文剖析,这可能是Python代码数据量、模型参数量有余等起因导致的。此外,作者们也提到,做出PolyCoder的目标次要还是为了开源一个AI代码生成模型,让更多人参加钻研和应用。 目前代码曾经开源,无论是间接拿来用,还是试着在它的根底上开发新模型都能够。 感兴趣的小伙伴能够上手一试了~

August 16, 2022 · 1 min · jiezi

关于c++:理解qt的qList以及函数传参

数组四种类型栈,堆 qDebug() << "test_stack_heap start"; Entity *entity1 = nullptr; Entity *const *p = nullptr; { MyList<Entity *> myList; entity1 = new Entity(1, "entity1"); myList.push_back(entity1); qDebug() << "myList 地址:" << &myList << ",数组指针变量地址:" << &myList.at(0) << ",数组指针变量指向的内存地址:" << myList.at(0); // 1.传值 qDebug() << "funcParam"; funcParam(myList); // 2.传指针 qDebug() << "funcParamPointer"; funcParamPointer(&myList); // 3.传援用 qDebug() << "funcParamRef"; funcParamRef(myList); p = &(myList.at(0)); qDebug()<< (**p).id(); // myList被删除前(函数体完结主动删除),能够拜访到数组内元素地址,进而取得堆内存里的entity内容运行后果: mylist变量存于栈内存,Entity指针变量存于栈内存(数据量大的时候QList会存数据到堆内存),Entity指针指向的Entity内容存于堆内存生命周期完结后mylist开释,Entity指针变量开释,Entity指针指向的Entity内容不开释(需手动delete) 传参: 传值将mylist的Entity指针变量拷贝复制到list里,此时,list与mylist地址不一样,list的指针变量地址与mylist的指针变量地址不一样,list的指针变量指向的内容与mylist的指针变量指向的内容一样传指针将mylist的地址作为参数传递,此时只会有地址的拷贝,list的地址与mylist的地址将会一样,指针变量的地址也一样,指针变量指向的内容地址也一样传援用传援用与传指针一样栈,栈 qDebug() << "test_stack_stack start"; Entity const *p = nullptr; { MyList<Entity> myList; Entity entity1(1, "entity1"); myList.push_back(entity1); qDebug() << "myList 地址:" << &myList << ",数组内容地址:" << &myList.at(0); // 1.传值 qDebug() << "funcParam"; funcParam(myList); // 2.传指针 qDebug() << "funcParamPointer"; funcParamPointer(&myList); // 3.传援用 qDebug() << "funcParamRef"; funcParamRef(myList); p = &(myList.at(0)); qDebug()<< (*p).id(); // myList被删除前(函数体完结主动删除),能够拜访到数组内元素,取得数组存储的entity内容 } qDebug() << (*p).id(); //此时数组被开释,类指针被开释,无奈再通过其拜访 qDebug() << "test_stack_stack end";运行后果: ...

August 16, 2022 · 5 min · jiezi

关于c++:CC气象数据中心实战手把手教你做工业级项目无密分享

C/C++气象数据中心实战,手把手教你做工业级我的项目|无密分享下载地址:百度网盘Java中如何斯文的处理异样对于后端程序员来说,写Java程序的时候,处理异样是必须要做的事。谬误处理诚然重要,然而若是被谬误处理霸占了大部分逻辑,那么就大错特错了。最近对这一点略有研究,稍微提一些斯文的处理异样的技巧和思路。1 使用异样而不是返回码咱们先看如下代码例子public void demo01(Long userId){ String userName = getUserName(userId);if (StringUtils.isNotEmpty(userName)) { //持续之后的逻辑} else { log.info("没有获取到用户名称");}}复制代码若是执行这段代码的时候,userName为空,会影响接下来的逻辑。可是若是只是输入一段日志,刚写代码的时候,比较熟悉,查看起来容易,然而工夫久了或者后边的同学接手代码的时候就有点烦脑了。最好是间接抛出异样,既然已经影响到接下来的逻辑了,那就抛出异样,阻断过程。如下所示:public void demo02(Long userId){ String userName = getUserName(userId);if (StringUtils.isNotEmpty(userName)) { //持续之后的逻辑} else { throw new BusinessException("没有获取到用户名称");}}复制代码2 使用不可控异样若是使用可控异样,那么在多层封装的时候,需要在每个catch块中申明这个异样,若是在最底层的方法中新增了一个可管制异样,那么每个调用此方法的函数都要新增一个throw语句。就像如下代码所示,当getManager新增一个可控异样,那么demo03绝对应也要新增一个catch块。调用demo03的方法也要新增。以此类推,那么就是从最底层到最高层的一个修改链。public void demo03(Long userId) throws Exception { try { String userName = getManager(userId); //持续之后的逻辑} catch (BusinessException e) { throw e;} catch (Exception e) { throw new Exception(e);}} private String getManager(Long userId) throws Exception { try { //获取以后用户的manager} catch (BusinessException e) { throw new BusinessException("获取manager失败");} catch (Exception e) { throw new Exception(e);}return "manager";}复制代码3 给异样提供更多的信息当抛出异样的时候,提供更多的信息,有助于找到问题并疾速解决。能从谬误日志中获取到足够多的信息,来准确分析发生谬误的原因,是一件如许美妙的事件。如下例子,通过错误信息可能看到是获取谁的manager失败了,查看数据库和代码逻辑可能疾速定位问题。若是有其余信息,一并传入会有更大的帮助。public void demo04(Long userId) throws Exception { ...

August 14, 2022 · 1 min · jiezi

关于c#:树形结构数据获取

记录代码如下: /// <summary> /// 返回树形下拉框 菜单数据 /// </summary> /// <returns></returns> [HttpGet] public ActionResult GetTreeList(int hosid=0,int pid=0) { var hoslist = yqBll.GetListall(); var dptmodel = departmentBLL.GetModelList(" F_State=1"); dptmodel.Sort((x, y) => x.F_Sort ?? 0 - y.F_Sort ?? 0);//排序 var treeList = new List<TreeModel>(); if (hoslist.Count > 0) { foreach (var hositem in hoslist) { TreeModel treeModel = new TreeModel(); treeModel.id = hositem.T_Woid.ToString(); treeModel.IconCls = ""; treeModel.text = hositem.T_Woname; treeModel.parentid = "-1"; treeModel.TypeId = 1; treeModel.children = TreeRecursion(dptmodel, "0", hositem.T_Woid); treeList.Add(treeModel); //var dptlist = dptmodel.Where(p => p.F_ParentId == 0 && p.T_Woid == hositem.T_Woid).ToList(); } } //return Content(treeList.ToJson()); return Success("获取菜单树胜利", treeList); } private List<TreeModel> TreeRecursion(List<Model.T_Sys_Department> data, string parentId = "0", int hosid = 0) { List<Model.T_Sys_Department> item = null; List<TreeModel> newList = new List<TreeModel>(); //if (parentId != "0") //{ if (hosid != 0) { item = data.FindAll(t => t.F_ParentId.ToString() == parentId && t.T_Woid == hosid);//data倡议在调用此扩大办法前曾经排序过 } else { item = data.FindAll(t => t.F_ParentId.ToString() == parentId);//data倡议在调用此扩大办法前曾经排序过 } if (item.Count > 0) { foreach (Model.T_Sys_Department entity in item) { TreeModel treeModel = new TreeModel(); treeModel.id = entity.F_DeptId.ToString(); treeModel.IconCls = ""; treeModel.text = entity.F_DeptName; treeModel.parentid = entity.F_ParentId.ToString(); treeModel.TypeId = 2; treeModel.children = TreeRecursion(item, entity.F_DeptId.ToString()); newList.Add(treeModel); } } //} return newList; }

August 11, 2022 · 1 min · jiezi

关于c++:C基础知识

原文链接 1 static关键字加了 static 关键字的全局变量只能在本文件中应用。 static 定义的动态局部变量调配在数据段上,一般的局部变量调配在栈上,会因为函数栈帧的开释而被开释掉。 1.1 全局动态变量在全局变量前加上关键字 static,全局变量就定义成一个全局动态变量。内存中的地位:动态存储区,在整个程序运行期间始终存在。初始化:未经初始化的全局动态变量会被主动初始化为 0(主动对象的值是任意的,除非他被显式初始化);作用域:全局动态变量在申明仅在本文件可见,他的文件之外是不可见的,精确地说是从定义之处开始,到文件结尾。 1.2 部分动态变量在局部变量之前加上关键字 static,局部变量就成为一个部分动态变量。内存中的地位:动态存储区,在整个程序运行期间始终存在。初始化:未经初始化的全局动态变量会被主动初始化为 0(主动对象的值是任意的,除非他被显式初始化);作用域:作用域仍为部分作用域,当定义它的函数或者语句块完结的时候,作用域完结。然而当部分动态变量来到作用域后,并没有销毁,而是依然驻留在内存当中,只不过咱们不能再对它进行拜访,直到该函数再次被调用,并且值不变; 1.3 动态函数在函数返回类型前加 static,函数就定义为动态函数。函数的定义和申明在默认状况下都是 extern 的,但动态函数仅在本文件可见,不能被其余文件所用。函数的实现应用 static 润饰,那么这个函数只可在本 cpp 内应用,不会同其余 cpp 中的同名函数引起抵触;warning:在头文件中申明非static 的全局函数,在 cpp 内申明static 的全局函数,如果你要在多个 cpp 中复用该函数,就把它的申明提到头文件里去,否则 cpp 外部申明需加上 static 润饰; 1.4 类的动态成员对一个类中成员变量和成员函数来说,加了 static 关键字,则此变量/函数就没有 this指针了,必须通过类名拜访。 在类中,动态成员能够实现多个对象之间的数据共享,并且应用静态数据成员还不会毁坏暗藏的准则,即保障了安全性。因而,动态成员是类的所有对象中共享的成员,而不是某个对象的成员。对多个对象来说,静态数据成员只存储一处,供所有对象共用。 1.5 类的动态函数动态成员函数和静态数据成员一样,它们都属于类的动态成员,它们都不是对象成员。因而,对动态成员的援用不须要用对象名。在动态成员函数的实现中不能间接援用类中阐明的非动态成员,能够援用类中阐明的动态成员(这点十分重要)。如果动态成员函数中要援用非动态成员时,可通过对象来援用。从中可看出,调用动态成员函数应用如下格局:<类名>::<动态成员函数名>(<参数表>); 2 C++和C的区别2.1 设计思维上C++是面向对象的语言,而 C 是面向过程的结构化编程语言 2.2 语法上C++具备重载、继承、多态三种个性;C++相比 C,减少多许多类型平安的性能,比方强制类型转换;C++反对范式编程,比方模板类、函数模板等。 3 C++中四种cast转换C++中四种类型转换是:static_cast, dynamic_cast, const_cast, reinterpret_cast 3.1 const_cast用于将 const 变量转为非 const。它也是四个强制类型转换运算符中惟一可能去除 const 属性的运算符。对于未定义 const 版本的成员函数,咱们通常须要应用 const_cast 来去除 const援用对象的 const,实现函数调用。另外一种应用形式,联合 static_cast,能够在非 const 版本的成员函数内增加 const,调用完 const 版本的成员函数后,再应用 const_cast 去除 const限定。 ...

August 8, 2022 · 6 min · jiezi

关于c:编程利器-实用的CC语言在线编译器

无论应用什么语言编程,编译器始终是一个绕不开的问题。很多学习编程的小伙伴往往在开发环境装置、配置这一步,提前解锁了从入门到放弃的成就。 大家可能在学习编程语法的时候并不感觉太难,却在奇怪的中央被编译器卡住了。很多人可能花了微小的心理和工夫下载、装置并且进行各种配置,到头来却发现编译器没法应用而被浇了一盆冷水,学习编程的劲儿也因而被耗费磨损掉了。 明天次要来安利一款反对C语言、 C++、 Java、Python、Go等多种语言的在线编译器:Lightly IDE(https://lightly.teamcode.com/c)。 以C语言在线编译器为例,大家只须要在浏览器关上就能够开始编程并一键运行: 抉择编程语言和版本,让C语言在线编译器主动创立我的项目文件。 我的项目文件创建好后,就能够在编辑区编写代码了。实现后,只须要点击右上角的运行键就能够应用C语言在线编译器一键编译并运行代码。 与其余本地编译器不同,这款C语言在线编译器能够不依靠于本地环境也不须要用户手动进行各种简单配置。在文件治理上也非常业余,用户只须要登录本人的账号便能够在任何设施上拜访主动保留在云端的我的项目文件。 在编程的过程中,咱们还能在C语言在线编译器中应用断点性能调试代码,解决代码中的各种bug。 最初,心愿这款C语言在线编译器能帮忙大家在学习编程的路上更轻松、更便捷,同时也帮忙大家无需再受本地编译环境的限度,逾越不同设施随时随地编程。

August 6, 2022 · 1 min · jiezi

关于c:假如有n个台阶一次只能上1个台阶或2个台阶请问走到第n个台阶有几种走法

2023王道作业week4_day12————走楼梯1.题目:如果有n个台阶,一次只能上1个台阶或2个台阶,请问走到第n个台阶有几种走法?为便于读者了解题意,这里举例说明如下:如果有3个台阶,那么总计就有3种走法:第一种为每次上1个台阶,上3次;第二种为先上2个台阶,再上1个台阶;第三种为先上1个台阶,再上2个台阶。输出为n,输入为走到第n个台阶有几种走法 2.思路设台阶为n个 当n=1时,走法为1当n=2时,走法为2,1+1或2当为n个时,相当于在n-1这个台阶走一步或者在n-2这个台阶走两两步所以n个台阶相当于n-1个台阶的走法加上n-2个台阶的走法 递归函数 :ways(n) = ways(n-1) + ways(n-2);递归进口:n=1 return 1;n=2 return 2; ### 代码实现//如果有n个台阶,一次只能上1个台阶或2个台阶,请问走到第n个台阶有几种走法?//为便于读者了解题意,这里举例说明如下:如果有3个台阶,那么总计就有3种走法:第一种为每次上1个台//阶,上3次;第二种为先上2个台阶,再上1个台阶;第三种为先上1个台阶,再上2个台阶。输出为n,输入//为走到第n个台阶有几种走法 include<stdio.h>int ways(int n){ if (n == 1){ return 1;}if (n == 2){ return 2;}return ways(n - 1) + ways(n - 2);}int main(){ int n;scanf("%d", &n);int result = ways(n);printf("%d\n", result);return 0;}

August 4, 2022 · 1 min · jiezi

关于c++:C多态

什么是多态多态是指调用同一个函数时,呈现不同的成果。多态分类动态的多态:函数重载就是动态的多态动静的多态:用父类的指针或援用调用虚函数虚函数虚函数是指:类的成员函数被 virtual 润饰的函数(一般函数不能用virtual润饰)留神: 内联函数理论是没有地址的,然而如果内联函数被virtual润饰,则编译器会疏忽函数的内联属性,把它当做失常函数应用。动态成员函数是不能作为虚函数的,因为动态函数调用时不会隐式传入this指针,所以动态成员函数无奈放入虚函数表。构造函数不能是虚函数,因为构造函数阶段,虚表还没有初始化,所以构造函数不能是虚函数。有虚函数的类,编译器会主动减少一个成员变量(虚表指针,指向虚表(函数指针数组)) 例如下列类,sizeof(A) == 12理论的成员变量为:1个指针类型,一个int类型,一个char类型依据对齐规定,所以类的大小为 12 字节。class A{public: virtual void test() //这个就是虚函数 {} int a; char b;}继承中形成多态的条件必须通过父类的指针或援用调用虚函数被调用的函数必须是虚函数,且子类必须对虚函数进行笼罩。 留神:虚函数的笼罩,必须是返回类型、函数名、参数列表都雷同才行。如果返回值是父类、子类的指针或援用时,返回值不同也能够形成虚函数笼罩(协变)如果父类的析构函数为虚函数,则子类的析构函数只有定义(无论是否virtual润饰),都与父类的虚析构函数形成笼罩。(析构函数自身函数名就不雷同)class A{public: virtual void test() //这个就是虚函数 {}}class B{ public: virtual void test() //笼罩父类的虚函数 {} }虚函数的重写(笼罩)子类会继承父类的虚函数,如果子类有父类虚函数的重写时,就会将重写的虚函数地址笼罩父类虚函数的地址。 留神:虚函数的重写,是从新实现父类的虚函数,所以重写的函数参数要应用父类的参数。下列代码运行后果为:B->0class A{public: virtual void test1(int a = 0) { cout << "A->" << a << endl; } virtual void test() //父类函数被子类调用 { test1(); //这里其实隐含了一个this,即this->test1() //子类调用test,传递指针p,所以这里是 p->test1() } };class B :public A{public: virtual void test1(int a = 1) { cout << "B->" << a << endl; //实践上这里应该是输入B->1 //然而这个函数重写父类的函数,是实现父类的函数 //所以a在这里要应用父类的a = 0 }};int main(){ B* p = new B; //创立子类 p->test(); //子类调用父类成员 return 0;}虚析构函数的笼罩下列 类A 的析构函数被申明为虚函数,子类的析构函数与父类形成笼罩class A{public: virtual ~A() //父类的析构函数申明为虚函数 { cout << "~A" << endl; }};class B :public A{public: ~B() //与父类的虚析构函数形成笼罩 { cout << "~B" << endl; }};int main(){ A* p1 = new A; A* p2 = new B; delete p1; delete p2; return 0;}形成笼罩后,delete p2时,会先调用子类的析构函数,再调用父类的析构函数。如果没有形成笼罩,则delete p2时只会调用父类的析构函数。关键字final和overridefinal:润饰虚函数,使虚函数不能被笼罩。(加在父类中) ...

August 3, 2022 · 2 min · jiezi

关于c++:QT-C类成员函数如何作为回调函数

在c++里,当设计一个底层类的时候,上游不晓得上游具体的类是什么,又须要调上游的办法(比方通过通信获取到了数据,须要将数据回传到上游),解决办法是将上游类的成员函数(其余函数同理)充当回调函数,传递给上游。 上游类:mainwindow #ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QMainWindow>class ServerProvider;QT_BEGIN_NAMESPACEnamespace Ui {class MainWindow;}QT_END_NAMESPACEclass MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow() override; void getData(const QString &str); private: Ui::MainWindow *ui; ServerProvider *m_serverProvider;};#endif // MAINWINDOW_H#include "mainwindow.h"#include <functional>#include "serverprovider.h"#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); FuncDef func; func = std::bind(&MainWindow::getData, this, std::placeholders::_1); m_serverProvider = new ServerProvider(); m_serverProvider->setFunc(func);}MainWindow::~MainWindow() { delete ui; }void MainWindow::getData(const QString &str) { qDebug() << "GET DATA: " << str;}上游类:serverprovider ...

August 3, 2022 · 1 min · jiezi

关于c#:C语言经典题刷题打卡日记

温故而知新,最近几天从新回顾下这个月刷过的c语言题目 1. 三个数由小到大排序输出任意3个整数,编程实现对这3个整数进行由小到大排序井将排序后的结果显示在屏幕上 #include <stdio.h>#include <stdlib.h>int main(){ int a, b, c, t; printf("请任意输出三个数(空格分隔):\n"); scanf("%d %d %d", &a, &b, &c); if (a < b) { t = a; a = b; b = t; } else if (a < c) { t = a; a = c; c = t; } else if (b < c) { t = b; b = c; c = t; } printf("从大到小排列为:%d %d %d\n", a, b, c); system("pause"); return 0;}2. a²+b²要求输出整数a和 b, 若a²+b²的后果大与100, 则输入a²+b²的值,否则输入 a+b 的后果 ...

July 31, 2022 · 2 min · jiezi

关于c:如何在C语言中定义自己的数据类型

在C语言编程中,咱们其实能够关上编程语言的拘谨,本人定义本人想要的数据类型。只有记住 struct 和 typedef 两个关键词,咱们就能够通过C语言中的数据结构和共用体来保留非同质化的数据类型。 定义新的数据类型首先,在C语言在线编译器中输出以下代码: typedef struct student_structure { char* name; char* surname; int year_of_birth;} student;实现后,这段代码会把 student 预存为保留词,那样咱们能创立 student 类型的变量了。 那么这个新变量到底是怎么形成的呢?咱们所创立的这个结构化新变量是通过一系列根底变量组成的。在下面的代码中,咱们把 char name、char surname 这些变量组成了新的 student 变量中,其实就是放到内存块的一个名下。 应用新数据类型咱们当初创立好新的 student 变量后,能够在C语言在线编译器中为它初始化一些属性: student stu; strcpy(stu.name, "John"); strcpy(stu.surname, "Snow"); stu.year_of_birth = 1990; printf("Student name : %s\n", stu.name); printf("Student surname : %s\n", stu.surname); printf("Student year of birth : %d\n", stu.year_of_birth);在下面的例子中,眼尖的你可能曾经发现了咱们须要为新数据类型的所有变量调配一个值。除了应用 stu.name 来拜访外,咱们还能够应用更短的形式来为这些构造调配值: typedef struct { int x; int y;} point;point image_dimension = {640,480};你也能够应用不同的程序来设定值:point img_dim = { .y = 480, .x = 640 }; ...

July 29, 2022 · 1 min · jiezi

关于c#:纯手撸WinForm的Alert提示弹出框

纯手撸WinForm的Alert弹框一、窗体设置设置以下属性: 属性名属性值阐明AutoScaleModeNone确定屏幕分辨率或字体更改时窗体如何缩放BackColor103, 194, 58背景色FontMicrosoft Sans Serif, 14.25pt字体FormBorderStyleNone标题栏和边框款式ShowIconFalse是否显示窗体图标ShowInTaskBarFalse是否显示在Windows任务栏Size450,100窗体大小TopMostTrue窗口置顶二、界面控件两个PictureBox和一个Label以及一个定时器,控件大小大家本人定义吧,PictureBox设置SizeMode的值为Zoom,Label的ForeColor为white,AutoSIze为True。 成果如下: 三、代码以及思路1.首先新建三个枚举类:AlertTypes.cs、ActionType.cs、ShowDirection.csAlertTypes管制弹框的类型,ActionType弹框的状态,ShowDirection弹框的显示地位 public enum AlertType{ /// <summary> /// 胜利 /// </summary> Success, /// <summary> /// 提醒 /// </summary> Info, /// <summary> /// 谬误 /// </summary> Error, /// <summary> /// 正告 /// </summary> Warning}public enum ActionType{ /// <summary> /// 期待 /// </summary> wait, /// <summary> /// 开启 /// </summary> start, /// <summary> /// 敞开 /// </summary> close}public enum ShowDirection{ /// <summary> /// 头部核心 /// </summary> TopCenter, /// <summary> /// 右下角 /// </summary> BottomRight, /// <summary> /// 右上角 /// </summary> TopRight,}2.思路1.滑动的成果通过能够通过定时器批改地位 ...

July 26, 2022 · 5 min · jiezi

关于c++:设备码打印量产工具

源代码 目标设施码量产工具实现了从手持扫码枪(一维码、二维码)到设施码生成再到设施标签贴纸打印的自动化 其中设施码生成规定反对 lua 脚本自定义,可实用于更多场景 留神仅反对 win 零碎,以后已测试 win10 及以上版本对于扫码枪,硬件需应用 USB-KBW 接口对于标签打印机 (以后标签排版尺寸,60mm x 40mm) 须在控制面板中可看到待应用的打印机需将待使应用的打印机设置为默认打印机 *对于编码转换规则:程序会应用扫码枪或手动输出的原始值通过 LUA 自定义转换规则生成最终的设施码 规定转换文件 numconv.lua 在装置目录下可见返回 ”“ 示意谬误 装置双击 设施码量产工具_setup.exe 点击 下一步(可选的更换装置门路)![4.png](/img/bVc1i8j 点击 下一步 点击 装置 点击实现 应用双击快捷图标 设施码量产工具 点击 OK 保障桌面焦点始终处于 设施码量产工具 最下面的文本输入框 (可看到光标闪动) 启动形式扫码枪扫码失去一次数值手动编辑数值到 最下面的文本输入框,按下回车 数据操作,点击 导出本次 按钮,将导出自程序关上后所有无效的设施编码值(.csv) 留神需依照理论应用的打印机与标签纸设置对应的打印参数 (ZEBRA-ZD888 为例)

July 25, 2022 · 1 min · jiezi

关于c++:编辑中

Qt 文章汇总基于百问网 IMX6ULL 的综合性桌面零碎 - DBoSNotepad 实例开发简略考勤自定义组件合集简略录音,一个简略的小帮手视频播放器Qss 根底材料整顿手写体辨认opencv调用摄像头的简略利用基于TCP的网络聊天室SM4 加解密客户端MQTT 客户端自定义登录对话框繁难计算器程序设计虹软人脸识别SDK应用100ASK_IMX6ULL_PRO开发板QT移植过程阐明QTcpServer 多线程解决框架

July 22, 2022 · 1 min · jiezi

关于c#:C-11-的新特性和改进前瞻

.NET 7 的开发还剩下一个多月就要进入 RC,C# 11 的新个性和改良也行将敲定。在这个工夫点上,不少新个性都曾经实现结束并合并入主分支。C# 11 蕴含的新个性和改良十分多,类型零碎相比之前也有了很大的加强,在确保动态类型平安的同时大幅晋升了语言表达力。那么本文就依照方向从 5 个大类来进行介绍,一起来提前看看 C# 11 的新个性和改良都有什么。 类型零碎的改良▌形象和虚静态方法C# 11 开始将 abstract 和 virtual 引入到静态方法中,容许开发者在接口中编写形象和虚静态方法。接口与抽象类不同,接口用来形象行为,通过不同类型实现接口来实现多态;而抽象类则领有本人的状态,通过各子类型继承父类型来实现多态。这是两种不同的范式。在 C# 11 中,虚静态方法的概念被引入,在接口中能够编写形象和虚静态方法了。 interface IFoo{ // 形象静态方法 abstract static int Foo1(); // 虚静态方法 virtual static int Foo2() { return 42; }}struct Bar : IFoo{ // 隐式实现接口办法 public static int Foo1() { return 7; }}Bar.Foo1(); // ok因为运算符也属于静态方法,因而从 C# 11 开始,也能够用接口来对运算符进行形象了。 interface ICanAdd<T> where T : ICanAdd<T>{ abstract static T operator +(T left, T right);}这样咱们就能够给本人的类型实现该接口了,例如实现一个二维的点 Point: ...

July 22, 2022 · 7 min · jiezi

关于c++:OneFlow源码阅读6自动微分机制

深度学习框架个别通过主动微分(autograd)机制计算梯度并反向流传。本文尝试通过一个简略的例子、浅显地察看一下OneFlow的autograd的实现机制。OneFlow刚刚曾经公布了v0.8.0。这个文档仍是基于v0.7.0的代码。 1 主动微分根底主动微分相干的材料比拟多,个人感觉主动微分的原理介绍这个系列及其援用的材料对相干背景常识的介绍比拟残缺清晰。上面分几种状况对梯度流传的原理做一些直观解释。 1.1 stack网络的梯度流传以x -> f -> g -> z这个stack网络为例,依据链式法则: ∂z/∂x = ∂z/∂g * ∂g/∂f * ∂f/∂x理论运行时,在梯度反向流传过程中: z将∂z/∂g传给g。如果节点g有权重w须要计算梯度,就计算∂z/∂w = ∂z/∂g * ∂g/∂w。g须要计算∂g/∂f,再乘以z传过来的梯度,将后果传给f。g只须要给f传递链式乘积的后果,不须要传递各项明细。在训练阶段的前向计算时,g须要保留∂g/∂f计算依赖的两头后果、以供反向计算时应用。其它节点的流传状况顺次类推。1.2 简略graph的梯度流传以上面这个简略的graph拓扑为例。 在持续之前,须要理解一下多元复合函数微分的根本公式。下图中,u和v都是对于x和y的函数,z是对于u和v的函数。依据这个公式能够晓得,z对x的梯度别离沿两条链路流传,z -> u -> x和z -> v -> x,节点x将两个梯度之和作为z对x的梯度。 1.3 简单graph的梯度流传再看一个拓扑略微简单点的例子: 上图能够视为x -> U -> L,其中U是e -> ... -> h的子图。f -> g的子图能够视为V。对于节点h来说,它须要把梯度传给g和k。对节点e来说,它须要对f和k传来的梯度求和,才是∂L/∂e。这样,L对x的梯度,仍能够按链路拆解,一条链路前后节点间的梯度是乘积关系,传入的多条链路梯度是加和关系。 这篇blog中有一个简直一样的拓扑图,给出了局部权重参数的梯度公式。 2 autograd中tensor相干的一些基本概念2.1 叶子节点OneFlow的autograd文档中介绍了leaf node和root node的概念。只有输入、没有输出的是leaf node,只有输出、没有输入的是root node。集体了解,如果把weight、bias、data视为计算图的一部分,这些节点就是叶子节点(op不是叶子节点)。尤其是从反向计算图的视角看,这些节点的grad_fn是空,反向流传到这些节点就会进行。 is_leaf和requires_grad有比拟亲密的关系,但二者又是独立的。PyTorch是这样解释的: requires_grad=false的节点都是叶子节点。比方data。requires_grad=true的节点如果是用户创立的,也是叶子节点。比方weight和bias。在梯度的反向计算过程中,只有叶子节点的梯度才会被填充。对于非叶子节点,如果要填充梯度信息,须要显式设置retain_grad=true。requires_grad=true才会计算、填充梯度。比方y = relu(x),y是op创立的、不是叶子节点。但如果x须要计算梯度,则y.requires_grad==true。但不须要为y填充梯度。对于叶子节点这个概念,目前找到的次要是直观形容,还没看到严格、清晰的定义。也可能是因为用户个别不会间接应用is_leaf,这个概念只是在浏览代码的时候才会波及到。上面的材料能够供进一步参考: What is the purpose of is_leaf?叶子节点和tensor的requires_grad参数2.2 tensor detachTensor的detach办法会创立一个新的tensor。新tensor的属性中 requires_grad = falseis_leaf = truedetach的意思是从grad的反向计算图中把tensor分离出来。新的tensor与原来的对象共享存储,但不参加反向图的拓扑结构。原有对象的requires_grad属性不变。比方上面的代码,批改一个对象的数据,另一个对象的数据也会扭转。 ...

July 20, 2022 · 2 min · jiezi

关于c#:再谈C-Winforms桌面应用程序实现跨窗体间委托传值实例

文章首发于 码友网 -- 《再谈C# Winforms桌面应用程序实现跨窗体间委托传值(实例)》 前言对于C# Winforms桌面应用程序跨窗体传值其实是一个陈词滥调的问题了。我之前在码友网也写过多篇C# Winforms桌面应用程序跨窗体传值的实例文章,比方: 《C# WINFORM窗体间通过委托和事件传值(自定义事件参数)--实例详解》 《C#/.NET WINFORM中应用委托和事件在类中更新窗体UI控件》 那为什么还要“再谈”C# Winforms桌面应用程序跨窗体委托传值呢?因为对于绝大多数C#&.NET老手来说,要学习并熟练掌握C#的委托,事件等是比拟难的知识点,须要开发者一直地学习和我的项目实际。 并且,实现C# Winforms窗体间传值的计划也并不止一种,本文将为C#&.NET开发者们演示应用一种非凡的委托(delegate)--Action来实现的跨窗体传值实例。 成果预览本实例次要演示的是联系人治理,其中包含新建联系人,联系人列表等性能。 实例的最终预览成果如下: 创立解决方案及我的项目关上Visual Studio 2022,创立一个用于测试的解决方案,命名为:WindowsFormsApp1,再在解决方案中创立名为WindowsFormsApp1的我的项目。 别离新建三个Winform窗体:FrmMain,FrmCreate,FrmList 和一个联系人的类Contact.cs 联系人类(Contact.cs)定义如下: using System;namespace WindowsFormsApp1.Models{ /// <summary> /// 联系人 /// </summary> public class Contact { public Guid Id { get; set; } public string Name { get; set; } public string Email { get; set; } }}主窗体FrmMain.cs using System;using System.Collections.Generic;using System.Windows.Forms;using WindowsFormsApp1.Models;namespace WindowsFormsApp1{ public partial class FrmMain : Form { private List<Contact> _contacts; public FrmMain() { _contacts = new List<Contact>(); InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { var frm = new FrmCreate(); frm.OnContactCreated = (contact) => { _contacts.Add(contact); }; frm.ShowDialog(); } private void button2_Click(object sender, EventArgs e) { var frm = new FrmList(_contacts); frm.ShowDialog(); } }}在主窗体,【新建联系人】按钮事件中,创立了FrmCreate的实例frm,同时为frm实例设置了回调(委托)OnContactCreated,这一步是委托传值的要害。 ...

July 19, 2022 · 1 min · jiezi

关于c++:C继承

继承继承是类中成员的复用。有元关系无奈被继承。继承的定义和应用办法下列父类成员 pri 为private,所以子类无法访问。其余成员子类皆可拜访。下列子类以protected 形式继承父类,所以子类的对象对父类的拜访权限最高为protected。父类中成员函数 Print() 为public,然而子类继承形式为 protected,所以子类对象对 Print()的拜访权限为 protected,无法访问。class Person //父类{public: void Print() { cout << "name:" << _name << endl; cout << "age:" << _age << endl; }protected: string _name = "bjf"; int _age = 18; private: int pri = 5;};class Student :protected Person //继承Person类,子类 public: void test() { cout << _name << endl; cout << _age << endl; Print(); }private: int code;};int main(){ Student xiaoming; xiaoming.test(); return 0;}继承形式只决定子类的对象对父类成员的最高拜访权限(最低权限取决于成员自身的权限),不影响子类对父类的拜访权限。子类能够拜访父类的所有成员,除了公有成员(只是不能拜访公有成员,然而子类依然继承了的)class默认的继承形式是private,struct默认继承形式是pubilc。类对象间的赋值规定能够将子类对象赋值给父类对象。(父类对象不能赋值子类对象)int main(){ Student bjf; Person man; man = bjf; //用子类对象赋值父类的对象,只将子类中继承的父类成员赋值过来,而子类本人的成员不论 Person* woman = &bjf; //woman指针,只代表bjf中的父类成员。 return 0;}继承中的作用域(对于暗藏)在继承的体系中,父类和子类有独立的作用域。如果父类和子类有同名成员,则须要表明该成员属于哪个类,否则会依据就近准则默认是子类的成员。(子类成员屏蔽了父类成员的间接拜访,这就是暗藏)留神:如果是同名成员函数,这个也是暗藏,须要指明属于哪个类(这个不是函数重载)class Person{public: int mun = 10;};class Student :public Person //继承Person类 {public: void test() { cout << mun << endl; //输入为 5,就近准则 cout << Person::mun << endl; //输入为 10 } int mun = 5;};int main(){ Student xiaoming; xiaoming.test(); return 0;}父类成员变量的初始化子类对父类成员变量的初始化,必须调用父类的构造函数进行初始化。留神: ...

July 19, 2022 · 1 min · jiezi

关于c++:C输入输出流IO流

输入输出过程 输入输出缓冲区的作用能够屏蔽低级IO的实现,低级IO的实现依赖操作系统自身,所以如果可能屏蔽这部分的差别,能够很容易写出可移植程序。cin从控制台读取数据时,空格示意将数据存储在不同的缓冲区(一个cin有一个缓冲区)string a;cin >> a; //输出 aa bb (两头有空格)cout << a << endl; //输入aa,输入第一个缓冲区的内容string a;cin >> a; //输出 aa bb (两头有空格)cout << a << endl; //输入aa,输入第一个缓冲区的内容cin >> a; //第二个缓冲区,在下面输出aa bb按回车后,就不会再次进行输出了cout << a << endl; //输入bb,第二个缓冲区内容。想要获取空格符,能够应用 getline()文件IO流<fstream>ifstream读文件explicit ifstream (const char* filename, ios_base::openmode mode = ios_base::in);filename :文件名(如果文件不存在,零碎不会主动创立文件,读取失败,零碎也不会报错)mode :操作文件的模式,默认为读文件ofstream写文件explicit ofstream (const char* filename, ios_base::openmode mode = ios_base::out);filename :文件名(如果文件不存在,则会主动创立一个文件)mode :操作文件的模式,默认为读文件上面的 >> 、 <<的文件操作形式是C++独有的,C没有。int main(){ ofstream ofs; string arr1 = "abcdef"; string arr2 = "192.168"; ofs.open("text.text", std::ofstream::out); //以写的模式关上文件 ofs << arr1 << " " << arr2; //向text.text文件中写入数据 ofs.close(); //敞开文件 ifstream ifs("text.text"); //以读的模式关上文件 ifs >> arr1 >> arr2; //读取8个字符,保留在arr中。 cout << arr1 << endl; cout << arr2 << endl; return 0;} ...

July 19, 2022 · 1 min · jiezi

关于c++:C模板

泛型编程泛型编程是指:应用一个非凡的类型(泛型)来定义变量,写一个模板函数,以适应传递不同类型的参数,下列的 T1 和 T2 就是一种泛型。 template <class T1,class T2>留神:模板不反对拆散编译,即申明在 .h 文件,定义在 .cpp 文件。然而能够在.h文件中定义,而后在蕴含这个h头文件的 .cpp 文件中利用。一般函数在编译时函数名会被编译称特殊符号。 int add(int a,int b); //编译时会被编译成 _Z4addii(?)而函数模板在编译阶段基本不会被编译为特殊符号,因为它没有实例化。所以在链接时,依据_Z4addii这个名字会找不到对应的函数原型。函数模板申明办法:template <class T> 示意将 T 申明为一种变量类型(泛型)依据传入的参数类型,T能够主动匹配对应的类型。这样就能够使一个函数能够用于不同变量类型中,减少函数的复用,这就是函数模板。不同中央调用函数模板时,调用的不是同一个函数,尽管都是同一个模板编译器在这里,将模板依据实参类型进行了实例化,实例化成不同的函数。留神:如果存在非模板函数的同名函数,如果条件雷同的状况下,则会优先调用非模板函数。template <class T1,class T2>T1 ADD(T1& x1, T2& x2){ return x1+x2;}int main(){ int a1 = 10, b1 = 20; char a2 = 5, b2 = 10; ADD(a1, b1); //这个与上面这个都是调用的Swap函数 ADD(a1, a2); //然而调用的不是同一个函数 cout << "a1 = " << a1 << " b1 = " << b1 << endl; cout << "a2 = " << a2 << " b2 = " << b2 << endl; return 0;} ...

July 19, 2022 · 1 min · jiezi

关于c:c语言实现点名系统

点名零碎分为两种,一种为反复点名,一种为不反复点名反复点名:顾名思义,随机点到后,下次兴许还会点到 反复点名 #define _CRT_SECURE_NO_WARNINGS#include <stdio.h>#include<string.h>#include <stdlib.h>#include <time.h>#include<conio.h>#define N 57 //同学人数int main(){ int num = 0; void menu(); scanf("%d", &num); switch (num) { case 1: void chongfu(); break; case 2: void buchongfu(); break; default: } return 0;}void menu(){ printf("请输出数字,进入不同模式"); printf("1.反复点名"); printf("2.不反复点名");}void chongfu(){ int list[N], i, j, r, k; const char* s[N] = { “aa".......57个同学名字,define定义数雷同,否则报错 };//人名单 printf(" 随机点名,输出'0'退出。\n"); while (1) { printf("请问想点几个:"); scanf("%d", &k); //输出人数 if (k == 0) break; if (k > N) { printf("输出谬误\n"); continue; } else { srand(time(NULL)); for (i = 0; i < k; i++) //生成不反复的随机数组 { while (1) { r = rand() % N; for (j = 0; j < i; j++) { if (list[j] == r) break; } if (j == i) { list[i] = r; break; } } } //输入人名 for (i = 0; i < k; i++) { printf("%s\n", s[list[i]]); } } } return;}不反复点名 ...

July 18, 2022 · 2 min · jiezi

关于c++:C内存管理

内存分类栈区、堆区、动态区、代码段 栈区 :用来存储局部变量、函数的形式参数(寄存长期变量)堆区 :动态内存调配动态区 :寄存动态变量、全局变量(程序完结时,才被销毁)代码段 :寄存函数体(类成员函数和全局函数)的二进制代码int globalvar = 10; //globalvar 存储于动态区(数据段)static int stglobalvar = 10; //stglobalvar 存储于动态区int main(){ static int stcavar = 10; //stcavar 存储于动态区 int locavar = 10; //locavar 局部变量,存储于栈 int num1[10] = { 1,2,3,4 }; //num1 数组存储于栈 char char2[] = "abcd"; //char2 存储于栈; *char2 存储于栈 const char* pchar3 = "abcd"; //pchar3 局部变量指针存储于栈中,*pchar3 存储于代码段中(常量区) int* ptr = (int*)malloc(sizeof(int) * 4); //ptr 局部变量指针存储于栈中; *ptr开拓的空间,存储于堆中 free(ptr);}内存透露什么是内存透露:因为某种原因导致程序未能开释不再应用的内存。内存透露不是指物理上的内存隐没,而是指失去了对某段内存的控制权(指针失落)C++动静申请内存newC++语法兼容C语言,所以C语言的malloc和realloc等都能够应用。C++语法还有新的办法能够动静申请内存空间——new和delete留神:malloc开拓的空间只能free,new开拓的空间只能delete。int main(){ int* ptr1 = (int*)malloc(sizeof(int) * 4); int* ptr2 = new int[10]; //开拓多个空间时,应用中括号 free(ptr1); delete[] ptr2; int* ptr3 = (int*)malloc(sizeof(int)); int* ptr4 = new int; //开拓单个空间时 free(ptr3); delete ptr4;}malloc和new的区别malloc和new在申请根本类型的空间时,都是一样的,没有区别。区别: ...

July 15, 2022 · 2 min · jiezi

关于c#:HybridCLR划时代的Unity原生C热更新技术

HybridCLR是一个个性残缺、零老本、高性能、低内存的近乎完满的Unity全平台原生C#热更计划。 HybridCLR裁减了IL2CPP的代码,使它由纯AOT Runtime变成“AOT+Interpreter“混合Runtime,进而原生反对动静加载Assembly,使得基于IL2CPP Backend打包的游戏不仅能在Android平台,也能在iOS、Consoles等限度了JIT的平台上高效地以AOT+interpreter混合模式执行。 HybridCLR开创性地实现了“Differential Hybrid Dll“技术。即能够对AOT Dll任意增删改,会智能地让变动或者新增的类和函数以Interpreter模式运行,但未改变的类和函数以AOT形式运行,让热更新的游戏逻辑的运行性能根本达到原生AOT的程度。 HybridCLR(wolong)原作者walon(focus-creative-games创始人)将该系列课程放入UWA学堂连载更新,现已【收费上线UWA学堂】,本文先带大家对HybridCLR——划时代的Unity原生C#热更新技术有个简略的理解,更多内容可返回UWA学堂查看。 1. 根底概念1.1 CLRCLR即Common Language Runtime,中文叫公共语言运行时,是让.NET程序执行所需的内部服务的汇合,是.NET平台的外围和最重要的组件,相似于Java的JVM。更具体介绍请看《公共语言运行时 (CLR) 概述》。 1.2 IL2CPPIL2CPP是Unity开发的跨平台CLR解决方案,诞生它的一个要害起因是Unity须要跨平台运行。但一些平台如iOS,这种禁止JIT并导致依赖JIT的官网CLR虚拟机无奈运行,而是必须应用AOT技术将Mananged程序提前转化为指标平台的动态原生程序后再运行。而Mono尽管也反对AOT,但性能较差以及跨平台反对不佳。 IL2CPP计划蕴含一套AOT运行时以及一套DLL到C++代码及元数据的转换工具,使得原始的C#开发的代码最终能在iOS这样的平台运行起来。 1.3 IL2CPP与热更新很可怜,不像Mono有Hybrid mode execution,可反对动静加载DLL。IL2CPP是一个纯动态的AOT运行时,不反对运行时加载DLL,因而不反对热更新。 目前Unity平台的支流热更新计划xLua、ILRuntime之类都是引入一个第三方VM(Virtual Machine),在VM中解释执行代码,来实现热更新。这里咱们只剖析应用C#为开发语言的热更新计划。这些热更新计划的VM与IL2CPP是独立的,意味着它们的元数据系统是不相通的,在热更新里新增一个类型是无奈被IL2CPP所辨认的(例如,通过System.Activator.CreateInstance是不可能创立出这个热更新类型的实例),这种看起来像,但实际上又不是的伪CLR虚拟机,在与IL2CPP这种简单的CLR运行时交互时,会产生极大量的兼容性问题,另外还有重大的性能问题。 一个大胆的想法是,是否有可能对IL2CPP运行时进行裁减,增加Interpreter模块,进而实现Mono hybrid mode execution这样机制?这样一来就能彻底反对热更新,并且兼容性极佳。对开发者来说,除了解释模式运行的局部执行得比较慢,其余方面跟规范的运行时没有区别。 对IL2CPP加以理解并且三思而行后的答案是——的确是可行的!具体分析参见第二节《对于HybridCLR可行性的思维试验》 。这个想法诞生了HybridCLR,Unity平台第一个反对iOS的跨平台原生C#热更新计划! 2. 原理HybridCLR裁减了IL2CPP运行时,将它由AOT运行时革新为“AOT + interpreter”双引擎的混合运行时,进而完满反对在iOS这种禁止JIT的平台上以解释模式无缝地运行动静加载的DLL。如下图所示: 更具体一些,至多须要实现以下性能: 加载和解析DLL元数据动静注册元数据,其中要害为Hook动静函数的执行流到解释器函数实现一个高效正确的解释器正确处理GC及多线程等运行时机制3. 个性3.1 规范运行时个性近乎残缺实现了ECMA-335标准,不反对的个性仅包含: 不反对Delegate的BeginInvoke,EndInvoke。纯正是感觉没必要实现。不反对MonoPInvokeCallbackAttribute。意味着你如果同时还接了Lua,你没法间接将热更新的C#函数注册到Lua中,但有一个不简单的方法能做到这点。因为HybridCLR极其残缺的实现,让应用HybridCLR后的C#开发体验跟Editor下Mono开发简直完全相同(除了调用一些IL2CPP没实现的.net framework函数,非专家级别的开发者难以结构出HybridCLR不反对的用例)。 另外,因为是运行时级别的实现,HybridCLR反对这些个性的同时,不须要你额定生成或者调整任何代码。对于开发者来说,相比Unity下原生C#开发,零额定的学习和开发成本。 3.2 AOT相干个性因为IL2CPP AOT模块的存在,IL2CPP比规范运行时多了一些不存在的机制,因而HybridCLR也有一些额定的个性: 反对应用Interpreter Assembly替换AOT Assembly(限度:必须不存在其余AOT Assembly对它的间接援用)。反对补充元数据机制,彻底反对AOT泛型,参见《AOT泛型限度及原理介绍》。反对AOT Hotfix,能够修复AOT模块的Bug。反对任意C#函数注册到Lua之类的虚拟机,不限于Static函数,并且也不须要MonoPInvokeCallbackAttribute。条件是注册和回调形式须要稍微调整。3.3 Unity相干个性 完满反对Unity的Assembly Def模块机制。完满反对代码中挂载热更新脚本,无应用场景限度完满反对资源上挂载热更新脚本,但要求打包工作流有少许调整,参见《MonoBehaviour相干工作流》。4. 与其余风行的C#热更新计划的区别从原理来说,HybridCLR简直将热更新技术做到实践上的极限,与以后所有支流热更新计划不在一个档次。 4.1 实质比拟HybridCLR是原生的C#热更新计划。艰深地说,IL2CPP相当于Mono的AOT模块,HybridCLR相当于Mono的Interpreter模块,两者合一成为残缺Mono。HybridCLR使得IL2CPP变成一个全功能的Runtime,原生(即通过System.Reflection.Assembly.Load)反对动静加载DLL,从而反对iOS平台的热更新。 正因为hHybridCLR是原生Runtime级别实现,热更新局部的类型与主工程AOT局部类型是齐全等价并且无缝对立的。能够随便调用、继承、反射或多线程,不须要生成代码或者写适配器。 其余热更新计划则是独立VM,与IL2CPP的关系实质上相当于Mono中嵌入Lua的关系。因而类型零碎不对立,为了让热更新类型可能继承AOT局部类型,须要写适配器,并且解释器中的类型不能为主工程的类型零碎所辨认。个性不残缺、开发麻烦、运行效率低下。 4.2 理论应用体验或者个性比拟 HybridCLR学习和应用老本简直为零。HybridCLR让IL2CPP变成全功能的Runtime,学习和应用老本简直为零,简直零侵入性。而其余计划则有大量的坑和须要躲避的规定,学习和应用老本较高,须要对原我的项目作大量革新。HybridCLR能够应用所有C#的个性,而其余计划往往有大量的限度。HybridCLR中能够间接反对应用和继承主工程中的类型,其余计划要写适配器或者生成代码。HybridCLR中热更新局部元数据与AOT元数据无缝对立,像反射代码可能失常工作的,AOT局部也能够通过规范Reflection接口创立出热更新对象。其余计划做不到。HybridCLR对多线程反对良好。像多线程、ThreadStatic、Async等等个性都是HybridCLR间接反对,其余计划除了Async个性外均难以反对。HybridCLR中Unity工作流与原生简直完全相同。HybridCLR中热更新MonoBehaviour能够间接挂载在热更新资源上,并且正确工作。其余计划不行。HybridCLR兼容性极高。各种第三方库只有在IL2CPP下能工作,在HybridCLR下也能失常工作。其余计划往往要大量魔改源码。HybridCLR内存效率极高。HybridCLR中热更新类型与主工程的AOT类型齐全等价,占用一样多的空间。其余计划的等同类型则是假类型,不仅不能被Runtime辨认,还多占了数倍空间。HybridCLR执行效率高。HybridCLR中热更新局部与主工程AOT局部交互属于IL2CPP外部交互,效率极高。而其余计划则是独立虚拟机与IL2CPP之间的效率,不仅交互麻烦还效率低下。5. 运行性能理论性能如实践预计,全面并且大幅胜出以后支流的xLua、Puerts、ILRuntime之类的热更新计划。 根底指令(数值计算及条件跳转等指令),因为各个语言之间差距不大,因而胜出不显著。对象模型指令。因为没有跨语言交互的老本,简直是数倍到数十倍的晋升(如果指令本身耗费特地大,则差距不那么显著)。性能测试用例来自ILRuntime提供的规范测试用例,测试项目来自Don't worry的github仓库。 测试结果显示,绝大多数测试用例都有数倍到数十倍的性能差距,差距极其夸大。唯独数值计算跟xLua有大量劣势,这是因为以后HybridCLR未对指令作任何优化,后续优化版本大多数根底指令都将有100~300%的性能晋升。 6. 内存HybridCLR是运行时级别的实现,因为热更新的脚本,除了执行代码是以解释模式执行,其余形式跟AOT局部的类型是完全相同的,包含占用内存。 6.1 对象内存大小比照Lua的计算规定略简单,参见《Lua数据结构和内存占用剖析》。空Table占56字节,每多一个字段至多多占32字节。 ...

July 15, 2022 · 1 min · jiezi

关于c++:C-自定义二叉树并输出二叉树图形

原文链接 应用C++构建一个二叉树并输入。 输出输出根节点为10,顺次输出6、4、8、14、12、16 代码如下: #include <stdio.h>#include <stdlib.h>#include <vector>#include<iostream>#include <stack> #include<cstdlib>#include <string>using namespace std;struct TreeLinkNode // 定义二叉树{ int val; // 以后节点值用val示意 struct TreeLinkNode *left; // 指向左子树的指针用left示意 struct TreeLinkNode *right; // 指向右子树的指针用right示意 struct TreeLinkNode *parent; //指向父节点的指针用parent示意 TreeLinkNode(int x) :val(x), left(NULL), right(NULL), parent(NULL) { } // 初始化以后结点值为x,左右子树、父节点为空};//创立树TreeLinkNode* insert(TreeLinkNode* tree, int value){ TreeLinkNode* node = (TreeLinkNode*)malloc(sizeof(TreeLinkNode)); // 创立一个节点 node->val = value; // 初始化节点 node->left = NULL; node->right = NULL; node->parent = NULL; TreeLinkNode* temp = tree; // 从树根开始 while (temp != NULL) { if (value < temp->val) // 小于根节点就进左子树 { if (temp->left == NULL) { temp->left = node; // 新插入的数为temp的左子树 node->parent = temp; // temp为新插入的数的父节点 return tree; } else // 下一轮判断 temp = temp->left; } else // 否则进右子树 { if (temp->right == NULL) { temp->right = node; // 新插入的数为temp的右子树 node->parent = temp; // temp为新插入的数的父节点 return tree; } else // 下一轮判断 temp = temp->right; } } return tree;} // ************* 输入图形二叉树 *************void output_impl(TreeLinkNode* n, bool left, string const& indent){ if (n->right) { output_impl(n->right, false, indent + (left ? "| " : " ")); } cout << indent; cout << (left ? '\\' : '/'); cout << "-----"; cout << n->val << endl; if (n->left) { output_impl(n->left, true, indent + (left ? " " : "| ")); }}void output(TreeLinkNode* root){ if (root->right) { output_impl(root->right, false, ""); } cout << root->val << endl; if (root->left) { output_impl(root->left, true, ""); } system("pause");}// ***************************************// ====================测试代码====================int main(){ TreeLinkNode tree = TreeLinkNode(10); // 树的根节点 TreeLinkNode* treeresult; treeresult = insert(&tree, 6); // 输出n个数并创立这个树 treeresult = insert(&tree, 4); treeresult = insert(&tree, 8); treeresult = insert(&tree, 14); treeresult = insert(&tree, 12); treeresult = insert(&tree, 16); output(treeresult); // 输入图形二叉树}输入 ...

July 15, 2022 · 2 min · jiezi

关于c++:C-构建并复制二叉树

原文链接 应用C++构建一个二叉树并复制、输入。 程序#include <stdio.h>#include <stdlib.h>//#include <cstdio>#include <vector>#include<iostream>#include <stack> #include<cstdlib>#include <string>using namespace std;struct TreeNode // 定义二叉树{ int val; // 以后节点值用val示意 struct TreeNode *left; // 指向左子树的指针用left示意 struct TreeNode *right; // 指向右子树的指针用right示意 TreeNode(int x) :val(x), left(NULL), right(NULL) { } // 初始化以后结点值为x,左右子树为空};//创立树TreeNode* insert(TreeNode* tree, int value){ TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode)); // 创立一个节点 node->val = value; // 初始化节点 // malloc函数能够调配长度 node->left = NULL; node->right = NULL; TreeNode* temp = tree; // 从树根开始 while (temp != NULL) { if (value < temp->val) // 小于根节点就进左子树 { if (temp->left == NULL) { temp->left = node; // 新插入的数为temp的左子树 return tree; } else // 下一轮判断 temp = temp->left; } else // 否则进右子树 { if (temp->right == NULL) { temp->right = node; // 新插入的数为temp的右子树 return tree; } else // 下一轮判断 temp = temp->right; } } return tree;} // ************* 输入图形二叉树 *************void output_impl(TreeNode* n, bool left, string const& indent){ if (n->right) { output_impl(n->right, false, indent + (left ? "| " : " ")); } cout << indent; cout << (left ? '\\' : '/'); cout << "-----"; cout << n->val << endl; if (n->left) { output_impl(n->left, true, indent + (left ? " " : "| ")); }}void output(TreeNode* root){ if (root->right) { output_impl(root->right, false, ""); } cout << root->val << endl; if (root->left) { output_impl(root->left, true, ""); } system("pause");}// ******************************************void CopyBiTree(TreeNode* root, TreeNode* newroot) // 复制二叉树{ if (root == nullptr) return; else { newroot->val = root->val; if (root->left != nullptr) newroot->left = new TreeNode(0); if (root->right != nullptr) newroot->right = new TreeNode(0); CopyBiTree(root->left, newroot->left); CopyBiTree(root->right, newroot->right); } //output(newroot);}// ====================测试代码====================int main(){ TreeNode* tree =new TreeNode(10); // 树的根节点 TreeNode* treeresult; treeresult = insert(tree, 6); // 输出n个数并创立这个树 treeresult = insert(tree, 4); treeresult = insert(tree, 8); treeresult = insert(tree, 14); treeresult = insert(tree, 12); treeresult = insert(tree, 16); TreeNode* mirroot = new TreeNode(10); CopyBiTree(treeresult, mirroot); // 复制二叉树 output(treeresult); // 输入原二叉树 output(mirroot); // 输入复制的二叉树}后果 ...

July 15, 2022 · 2 min · jiezi

关于c++:C-创建链表并输出

原文链接 应用C++代码创立一个链表并输入: #include <stdio.h>#include <stdlib.h>//#include <cstdio>//#include <vector>#include<iostream>#include<cstdlib>using namespace std;//定义一个构造体 ListNode的构造struct ListNode { int val; //以后结点的值用val示意 struct ListNode *next; //指向下一个结点的指针用next示意 ListNode(int x) : val(x), next(NULL) { } //初始化以后结点值为x,指针为空};void print(ListNode *head) //打印输出链表{ ListNode *p = head; while (p != NULL) { cout << p->val; p = p->next; }}ListNode* CreateListNode(ListNode* pHead) // 创立链表{ ListNode* p = pHead; // 申明挪动指针,最开始指向头结点 for (int i = 1; i < 10; ++i) { ListNode* pNewNode; // 申明链表 pNewNode 来保留数据,pNewNode 就是一个链表的节点 pNewNode = new ListNode(0); // 初始化变量 pNewNode pNewNode->val = i; // 将新节点的值赋值为 i pNewNode->next = NULL; p->next = pNewNode; // p的下一节点指向这个新的节点,将此节点与头节点连贯 p = pNewNode; // p节点指向这个新的节点,向后挪动指针,以便下一次链接;p始终指向链表最初的一个节点 } return pHead;}int main(){ ListNode* head; // 申明头节点 head = new ListNode(0); // 头节点须要赋值能力调用 ListNode* p = CreateListNode(head); // 援用头节点创立链表 print(p); //援用打印 system("pause");}学习更多编程常识,请关注我的公众号: ...

July 15, 2022 · 1 min · jiezi

关于c#:开课预告79月学习课程基于MASA-Framework的EShop实战

July 14, 2022 · 0 min · jiezi

关于c#:容错熔断的使用与扩展

@[toc] 一、容错机制的介绍概念 当客户端调用微服务的时候,呈现了故障,可能进行故障转移,就是容错机制。如图: 目标保障微服务的高可用。 二、为什么应用容错机制故障转移机制如图:三、如何在微服务中利用容错机制实现条件 while实现步骤 int count = 0; //故障转移 for(int i=0;i<=3;i++) { //判断是否达到阀值 if (count == 3) { //退出循环,返回异样信息 throw Exception("微服务重试操作超出阀值"); } //业务代码 try { // HttpClient 申请微服务代码 ................... } catch(Exception ex) { //捕捉异样信息 count ++; } } 四、容错机制的缺点缺点 性能低,耗资源解决方案 设置固定的次数应用熔断机制 五、如何在微服务零碎中应用Polly熔断 概念熔断的是一个申请。当申请到服务器的时候,该申请重试了3次【测试次数】,没有申请胜利,间接熔断该申请,下次申请进来,不用再去重试,间接返回异样信息。条件 Polly代码实现 条件 装置 Polly步骤 装置 Microsoft.Extensions.Http.Polly在Startup.cs 文件中注册 办法名 ConfigureServices //异样降级信息 var fallBack = new HttpResponseMessage(){ Content = new StringContent("零碎忙!"), StatusCode = 504 }; //5:断路器阀值 //10:熔断工夫 //ExecutionRejectedException:捕捉熔断的所有异样信息 //10:应用的线程总数 services.AddHttpClient("micro[申请复用:自定义名称]") .AddPolicyHandler(Policy<HttpResponseMeaage>.Handle<ExecutionRejectedException>().Fallback(fallBack)) //异样信息降级 .AddPolicyHandler(Policy<HttpResponseMeaage>.Handle<Exception>().CircuitBreakerAsync(5,TimeSpan.FromSeconds(10))) //断路器 .AddPolicyHandler(Policy.TimeoutAsync<HttpResponseMeaage>(60))//设置超时工夫 .AddPolicyHandler(Policy<HttpResponseMeaage>.Handle<Exception>().RetryAsync(1))//重试次数 .AddPolicyHandler(Policy.BulkheadAsync<HttpResponseMeaage>(10,100));//资源(线程)隔离 //10:应用的线程总数 100:申请缓存总数业务代码 ...

July 13, 2022 · 1 min · jiezi

关于c++:类和对象

类类由两局部组成:成员变量(属性)、成员函数(成员的行为)在类中定义的成员函数,编译器会默认成内联函数。C++中将 struct 降级为类的定义(同样可能定义构造体,兼容C语言)C++中还能够应用 class 来定义类,用法跟struct雷同。类的申明与实例化struct People //还能够写为class People{public: //示意下列的都是私有的 void Init() //类中能够定义函数,构造体不行 { int a = 10; //Init函数在类的外部创立作用域,所以这里Init函数是定义 } void Push(); //Push函数是在里面定义的,这里只是申明(申明和定义拆散) int _a; //这里的成员变量都是申明,不是定义,在内存中开拓空间时能力称为定义。 char _b; struct People* _ptr;} void People:: Push(){ int a = 10;}int main(){ People man; //类的实例化}类的拜访限定符public :私有protected :爱护private :公有拜访限定符的作用范畴:以后拜访限定符的地位到下一个拜访限定符的地位,或者类完结。如果没有增加拜访限定符,class默认状况下是公有的,struct默认状况下是私有的。类的大小类中的函数被寄存在公共区域中(代码段)所以类的大小只思考成员变量的大小,不思考成员函数的大小。留神:思考成员变量大小时,遵循构造体的对齐规定。空类的大小为 1 ,给一个字节是为了占位,用来示意对象存在。class People{ char _b; int _a; short _c; void init() { }}int main(){ People man; cout << sizeof(man) << endl; //输入后果为 12 }面向对象的三大个性封装:将数据和操作数据的办法进行有机联合,暗藏对象的属性和实现细节,仅对外公开接口来和对象进行替换(其本质是一种治理)继承多态this指针在定义两个对象 today 和 tommor 时,调用 Init 函数,他们调用的是同一个函数。然而,这时 _year 等的成员变量就不好辨别到底是 today 的还是是 tommor 的。所以编译器就减少了一个隐含的参数 ...

July 11, 2022 · 4 min · jiezi

关于c++:C20-以-Bazel-Clang-开始

C++20 如何以 Bazel & Clang 进行构建呢? 本文将介绍: Bazel 构建零碎的装置LLVM 编译系统的装置 Clang is an "LLVM native" C/C++/Objective-C compilerBazel Clang 工具链的配置C++20 库与利用的构建本文示例可见: https://github.com/ikuokuo/st... 本文是于 Ubuntu 20 上进行的实际,Windows 能够用 WSL 筹备环境。 装置 Bazel,以二进制形式Bazelisk 是装置 Bazel 的举荐形式,咱们装置它的二进制公布即可: cd ~wget https://github.com/bazelbuild/bazelisk/releases/download/v1.12.0/bazelisk-linux-amd64 -O bazelisk-1.12.0-linux-amd64chmod a+x bazelisk-*sudo ln -s $(pwd)/bazelisk-1.12.0-linux-amd64 /usr/local/bin/bazeltouch WORKSPACE# 国内下载 Bazel 可能遇到如下问题,配置 .bazeliskrc 解决# could not resolve the version 'latest' to an actual version number# https://github.com/bazelbuild/bazelisk/issues/220cat <<-EOF > .bazeliskrcBAZELISK_BASE_URL=https://github.com/bazelbuild/bazel/releases/downloadUSE_BAZEL_VERSION=5.2.0EOFbazel version更多形式,可见官网文档。进一步,举荐装置 buildtools,下载后软链一下: sudo ln -s $(pwd)/buildifier-5.1.0-linux-amd64 /usr/local/bin/buildifiersudo ln -s $(pwd)/buildozer-5.1.0-linux-amd64 /usr/local/bin/buildozerBazel 如何构建 C++ 我的项目,可见我的 Start Bazel 笔记。 ...

July 11, 2022 · 4 min · jiezi

关于c++:C入门

命名空间namespacenamespace :命名空间,相当于定义了一个作用域,用来解决命名抵触问题。域作用限定符:拜访命名空间中的内容,应用双冒号 : : ,当: :右边为空时,示意应用全局域。// 定义第一个命名空间namespace first_space{ void func(){ int a = 1; cout << "Inside first_space" << endl; }}// 定义第二个命名空间namespace second_space{ void func(){ int a = 2; cout << "Inside second_space" << endl; }}int a = 10;int main (){ int a = 5; printf("%d\n",a); //a = 5 ,就近准则,应用a = 5的那个。 printf("%d\n",first_space::a); //a = 1 printf("%d\n",::a); //a = 10,::右边为空,代表应用全局域(全局变量) // 调用第一个命名空间中的函数 first_space::func(); // 调用第二个命名空间中的函数 second_space::func(); return 0;}using :using namespace 指令,这个指令会通知编译器,后续的代码将应用指定的命名空间中的名称,这样在应用命名空间时就能够不必在后面加上命名空间的名称。using namespace first_space;int main (){ // 调用第一个命名空间中的函数 func(); return 0;}嵌套命名空间,能够应用: :来拜访嵌套的命名空间。namespace namespace_name1 { // 代码申明 namespace namespace_name2 { // 代码申明 }}// 拜访 namespace_name2 中的成员using namespace namespace_name1::namespace_name2; // 拜访 namespace_name1 中的成员using namespace namespace_name1;C++库为了避免命名抵触,将本人库中的货色都定义在一个 std 的命名空间中所以有时候程序中都会调用 using namespace std; 这个库。#include <iostream> //援用.h头文件,为了与老版辨别,在新版中不必写.husing namespace std; //调用std库int main(){ cout << "hello world" << endl; //因为下面写了using,所以能够不写命名空间 std::cout << "hello world" << std::endl; //指定命名空间 return 0;}C++输出和输入C++的输入输出能够自动识别类型,不必手动表明。 ...

July 8, 2022 · 3 min · jiezi

关于c:typedef有四种用法你都会了吗

此篇博客适宜初学者浏览,心愿我的科普能为你的学习减少更多能源Typedef 是编程语言 C 和 C + + 中的一个保留关键字。它用于为另一个数据类型创立附加名称(别名) ,但不创立新类型,除非是数组类型的限定 typedef,其中 typedef 限定符被转移到数组元素类型。因而,它通常用于简化申明由 struct 和 union 类型组成的简单数据结构的语法,然而在为不同长度的整数数据类型提供特定的描述性类型名称时也同样常见。 1.为自定义数据类型(构造体、共用体和枚举类型)定义简洁的类型名称刚自学入门c的时候,坦率的说,我看的这个demo和输入后果,我对typedef的第一印象是替换,当然我对我当初的了解,在当初看来,也是可能解释的通的。 typedef struct tagPoint { double x; double y; double z; } Point;它理论等于 struct tagPoint { double x; double y; double z; } ;因为ponit转化成了构造体变量tagpoint 2.为根本数据类型定义新的类型名例如这样: typedef unsigned int ABC;可能看到这里,往往会想到构造体struct,具体区别能够参考 https://riptutorial.com/c/exa...,has%20to%20include%20the%20whole%20definition%20of%20bar.3.为数组定义简洁的类型名称例如这样: typedef int INT_ARRAY_100[100]; INT_ARRAY_100 arr;4.为指针定义简洁的名称 typedef char* PCHAR; PCHAR pa;以上就是全副区别了,如果你还有更多有意思或者更好的内容,欢送评论区补充

July 7, 2022 · 1 min · jiezi

关于c++:AddressSanitizer-技术初体验

简介 AddressSanitizer 是 Google 开发的一款用于检测内存拜访谬误的工具,用于解决 use-after-free 和内存透露的相干问题。它内置在 GCC 版本 >= 4.8 中,实用于 C 和 C++ 代码。AddressSanitizer 可在应用运行时检测跟踪内存调配,这意味着必须应用 AddressSanitizer 构建代码能力利用它的性能。 因为内存透露会减少程序应用的总内存,所以当不再须要内存时,正确开释内存很重要。或者对于小程序,失落几个字节仿佛没什么大不了的,然而对于应用大量内存的长时间运行的程序,防止内存透露变得越来越重要。如果程序不再须要它时,无奈开释应用的内存,很可能会耗尽内存,从而导致应用程序提前终止。AddressSanitizer 的呈现,就能够帮忙检测这些内存透露。 此外,AddressSanitizer 能够检测 use-after-free 谬误。当程序尝试读取或写入已被开释的内存时,会产生开释后应用谬误。这是未定义的行为,可能会导致数据损坏、后果不正确,甚至程序解体。 如果检测到谬误,程序将向 stderr 打印谬误音讯,并以非零退出代码退出,若是应用 AddressSanitizer,那么它在第一个检测到的谬误时就退出。 留神 ASan 应用本人的内存分配器(malloc, free 等)ASan 应用大量虚拟地址空间(x86_64 Linux 上为 20T) 应用 -fsanitize=address 标记用于通知编译器,将增加 AddressSanitizer,对应用调试符号编译代码很有帮忙。如果存在调试符号,须要 AddressSanitizer 打印行号,那么请增加 -g 标记。此外,如果您发现堆栈跟踪看起来不太正确,应用 -fno-omit-frame-pointer 就能够显示更具体的调用栈信息,合并成一条命令生成可执行文件: gcc main.cpp -o main -g -fsanitize=address此段代码为 Bash 或者,分成独自的编译和链接阶段: gcc -c main.cpp -fsanitize=address -g` -fno-omit-frame-pointergcc main.o -o main -fsanitize=address此段代码为 Bash 请留神,编译和链接步骤都须要 -fsanitize=address 标记。如果构建零碎更简单,将这些标记放在 CXXFLAGS 和 LDFLAGS 环境变量中。 ...

July 6, 2022 · 5 min · jiezi

关于c#:5-数据访问-EntityFramework集成

前言Masa提供了基于EntityFramework的数据集成,并提供了数据过滤与软删除的性能,上面咱们将介绍如何应用它? MasaDbContext入门装置.Net 6.0新建ASP.NET Core 空我的项目Assignment.MasaEntityFramework,并装置Masa.Contrib.Data.EntityFrameworkCore、Swashbuckle.AspNetCore、Microsoft.EntityFrameworkCore.InMemory、Microsoft.EntityFrameworkCore.Tools dotnet add package Masa.Contrib.Data.EntityFrameworkCore --version 0.4.0-rc.4dotnet add package Swashbuckle.AspNetCore --version 6.2.3dotnet add package Microsoft.EntityFrameworkCore.InMemory --version 6.0.5dotnet add package Microsoft.EntityFrameworkCore.Tools --version 6.0.5装置Swashbuckle.AspNetCore是为了不便通过Swagger来操作服务装置Microsoft.EntityFrameworkCore.InMemory是为了不便,因而应用内存数据库,如果须要应用其余数据库,请自行装置对应的包装置Microsoft.EntityFrameworkCore.Tools是为了应用CodeFirst创立数据库新建类User public class User{ public int Id { get; set; } public string Name { get; set; } public uint Gender { get; set; } public DateTime BirthDay { get; set; } public DateTime CreationTime { get; set; } public User() { this.CreationTime = DateTime.Now; }}新建用户上下文UserDbContext.cs ...

July 5, 2022 · 3 min · jiezi

关于c:数据结构与算法初级

复杂度解说算法效率算法效率分为两种:工夫效率(工夫复杂度)和空间效率(空间复杂度)它们别离掂量一个算法的运行工夫和所占的空间大小。工夫复杂度工夫复杂度计算的是一个函数中算法基本操作的执行次数。工夫复杂度针对的是一整个函数。工夫复杂度的计算方法(大O渐进表示法)大O渐进表示法是一种估算:只取表达式中对后果影响最大的一项。推导大O阶办法: 用数字1取代算数中的所有常数。在批改后的算数中,只保留最高项。如果最高阶存在且不是1,则去除这个项的常数,失去的后果就是大O阶。例如: 下列的工夫复杂度算数为 :F(N) = 2*N + 10所以大O阶表达式为 :O(N)void Fun1(int N){ int count = 0; for (int i = 0; i < 2 * N; i++) { ++count; } int M = 10; while (M--) { ++count; } printf("%d", count);}留神:当函数中未知数有多个时例如: 工夫复杂度表达式为:F(N) = M + N + 10 时,大O阶为 O(M+N) 或者 O(N)工夫复杂度表达式为:F(N) = 1000 时,大O阶为 O(1) (第一步将所有常数用1代替)O(1) 示意的是算法中基本操作执行常数次,而不是真的只执行一次。工夫复杂度表达式为:F(N) = M*M + N + 10 时,大O阶为 O(M^2)工夫复杂度中:为了不便个别把log2N(以2为底数)写作logN (log3N等就不会缩写了)所谓的线性工夫复杂度就是指O(N)。空间复杂度空间复杂度是对一个算法在运算过程中,长期占用的内存空间大小。空间复杂度不是计算程序占用了多少个字节,而是计算长期变量的个数。空间复杂度的计算方法也采纳大O渐进表示法。O(1) 代表常数个变量。递归算法的空间复杂度就是递归的深度乘以每个算法的空间复杂度(每递归一次,就会在栈中创立一个长期的函数)留神: 工夫是累计的,空间是能够复用的创立局部变量后,在程序出大括号后,就会销毁。程序表和链表线性表线性表是 n 个具备雷同个性的数据元素的无限序列常见的线性表:程序表、链表、栈、队列等。线性表在逻辑上是线性构造,但理论物理存储上通常是以数组和链式构造的模式存储的。程序表和链表程序表: ...

July 4, 2022 · 1 min · jiezi

关于c#:Modbus协议通信异常

@[toc] 一、Modbus协定通信异样地址范畴 从站地址:1-247:无效的地址范畴 0:播送数据异样(数据无奈失常解析) 大小端存储问题异样解决原理(响应异样) 由从机明确回复性能码高地位 1如图:异样信息含意 代码名称含意01非法性能对于服务器(或从站)来说,询问中接管到的性能码是不可容许的操作。这兴许是因为性能码仅仅实用于新设施而在被选单元中是不可实现的。同时,还指出服务器(或从站)在谬误状态中解决这种申请,例如:因为它是未配置的,并且要求返回寄存器值。02非法数据地址对于服务器(或从站)来说,询问中接管到的数据地址是不可容许的地址。特地是,参考号和传输长度的组合是有效的。对于带有100 个寄存器的控制器来说,带有偏移量96 和长度4的申请会胜利,带有偏移量96和长度5的申请将产生异样码02。03非法数据值对于服务器(或从站)来说,询问中包含的值是不可容许的值。这个值批示了组合申请残余构造中的故障,例如:隐含长度是不正确的。并不意味着,因为MODBUS 协定不晓得任何非凡寄存器的任何非凡值的重要意义,寄存器中被提交存储的数据项有一个应用程序冀望之外的值。04从站设施故障当服务器(或从站)正在设法执行申请的操作时,产生不可从新取得的过错。05确认与编程命令一起应用。服务器(或从站)曾经承受申请,并切正在解决这个申请,然而须要长的持续时间进行这些操作。返回这个响应避免在客户机(或主站)中产生超时谬误。客户机(或主站)能够持续发送轮询程序实现报文来确定是否实现解决。06隶属设施忙与编程命令一起应用。服务器(或从站)正在解决长持续时间的程序命令。张服务器(或从站)闲暇时,用户(或主站)应该稍后从新传输报文。08存储奇偶性过错与性能码20和21 以及参考类型6一起应用,批示扩大文件区不能通过一致性校验。服务器(或从站)设法读取记录文件,然而在存储器中发现一个奇偶校验谬误。客户机(或主方)能够从新发送申请,但能够在服务器(或从站)设施上要求服务。0A不可用网关门路与网关一起应用,批示网关不能为解决申请调配输出端口至输入端口的外部通信门路。通常意味着网关是谬误配置的或过载的。0B网关指标设施响应失败与网关一起应用,批示没有从指标设施中取得响应。通常意味着设施未在网络中。申请频率异样 RTU报文申请距离 3.5个字符工夫 1.5个字符工夫报文长度限度 0x07D0 线圈的单次申请长度0x007D 寄存器单词申请的长度

July 2, 2022 · 1 min · jiezi

关于c:C程序设计-10-文件操作

一、C 文件基本知识1. 文件与文件分类文件(flie)个别是指存储在内部介质(如磁盘)上的数据的汇合。操作系统是以文件为单位对数据进行治理的。文件有不同类型,C 语言中次要用到两种文件: 程序文件:包含源程序文件 .c、指标文件 .obj、可执行文件 .exe。文件的内容是程序代码。数据文件:文件的内容是供程序运行时读写的数据。咱们次要探讨的是数据文件。 C 语言把文件看作一个字符(或字节)的序列,即由一个一个字符(或字节)的数据程序组成。一个输入输出流就是一个字符流或字节(内容为二进制数据)流。C 的数据文件由一连串的字符(或字节)组成,对文件的存取是以字符(字节)为单位的。输入输出数据流的开始和完结仅受程序控制而不受物理符号(如回车换行符)管制,这就减少了解决的灵活性。这种文件称为流式文件。 一个文件要有惟一的文件标识,以便辨别和援用,这就是文件名。文件标识包含 3 局部:①文件门路;②文件名骨干;③文件后缀。如: D:\cProgram\temp\file1.dat工具数据的组织模式,将数据文件分为 ASCII 文件和二进制文件。数据在内存中是以二进制模式存储的,如果不加转换地输入到外存,就是二进制文件,能够认为它就是存储在内存的数据的映像,所以也称之为映像文件(image file)。如果要求在外存上以 ASCII 代码模式存储,则须要在存储前进行转换。ASCII 文件又称文本文件(text file),每一个字节寄存一个字符的 ASCII 代码。 用 ASCII 码模式输入时字节与字符一一对应,一个字节代表一个字符,因此便于对字符进行一一解决,也便于输入字符。但个别占存储空间较多,而且要花费转换工夫(二进制模式与 ASCII 码间的转换)。用二进制模式输入数值,能够节俭外存空间和转换工夫,把内存中的存储单元中的内容一成不变地输入到磁盘(或其余内部介质)上,此时每一个字节并不一定代表一个字符。如果程序运行过程中有的两头数据须要保留在内部介质上,以便在须要时再输人到内存,个别用二进制文件比拟不便。在事务管理中,常有少量数据寄存在磁盘上,随时调人十算机进行查问或解决,而后又把批改过的信息再存回磁盘,这时也罕用二进制文件。 2. 文件缓冲区ANSI C 规范采纳“缓冲文件系统”解决数据文件,所谓缓冲文件系统是指零碎主动地在内存区为程序中每一个正在应用的文件开拓一个文件缓冲区。从内存向磁盘输入数据必须先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘去。如果从磁盘向计算机读入数据,则一次从磁盘文件将一批数据输人到内存缓冲区(充斥缓冲区),而后再从缓冲区一一地将数据送到程序数据区(给程序变量)。这样做是为了节俭存取时间,提高效率,缓冲区的大小由各个具体的 C 编译系统确定。 3. 文件类型指针缓冲文件系统中,要害的概念是“文件类型指针”,简称文件指针。每个被应用的文件都会在内存中开拓一个相应的文件信息区,用来寄存文件的无关信息,这些信息是保留在一个零碎申明的构造体变量 FILE 中。例如,一种 C 编译环境提供的 stdio.h 头文件中有以下文件类型申明: typedef struct { short level; // 缓冲区“满”或“空”的长度 unsigned flags; // 文件状态标记 char fd; // 文件描述符 unsigned char hold; // 如缓冲区无内容不读取字符 short bsize; // 缓冲区大小 unsigned char* buffer; // 数据缓冲区的地位 unsigned char* curp; // 文件地位标记指针以后的指向 unsigned istemp; // 临时文件指示器 short token; // 用于无效查看} FILE;以上申明 FILE 构造体类型的信息蕴含在头文件 stdio.h 中。在程序中能够间接用 FILE 类型名定义变量。每一个 FILE 类型变量对应一个文件的信息区,在其中寄存该文件的无关信息。例如: ...

July 2, 2022 · 3 min · jiezi

关于c#:4-对象映射-MappingMapster

前言在我的项目中咱们会常常遇到对象的映射,比方像Model和Dto之间的映射,或者是对象的深拷贝,这些都是须要咱们本人实现的。此时,我的项目中会呈现很多初始化对象的代码,这些代码写起来相当的枯燥乏味,那么有没有什么方法加重咱们的工作量,使得咱们能够把工夫破费到业务性能上呢? 目前,.Net中的对象映射框架,功能强大且性能极佳的对象映射框架曾经存在,其中应用最多的有: MapsterAutoMapper说到对象映射框架,大家想到的最多的是AutoMapper,可能很多人连Mapster都没听过,但不可否认的是Mapster的确是一个很好的对象映射框架,但因为中文文档的缺失,导致在国内知名度不是很高,明天咱们就来介绍一下Mapster提供了哪些性能,如何在我的项目中应用它,Masa提供的Mapster又做了什么? Mapster 简介Mapster是一个应用简略,功能强大的对象映射框架,自2014年开源到当初曾经过来8个年头,截止到当初,github上曾经领有2.6k的star,并放弃着每年3次的发版频率,其性能与AutoMapper相似,提供对象到对象的映射、并反对IQueryable到对象的映射,与AutoMapper相比,在速度和内存占用方面体现的更加优良,能够在只应用1/3内存的状况下取得4倍的性能晋升,那咱们上面就来看看Mapster如何应用? 筹备工作新建一个控制台我的项目Assignment.Mapster,并装置Mapster dotnet add package Mapster --version 7.3.0映射到新对象新建类UserDto public class UserDto{ public int Id { get; set; } public string Name { get; set; } public uint Gender { get; set; } public DateTime BirthDay { get; set; }}新建一个匿名对象,作为待转换的对象源 var user = new{ Id = 1, Name = "Tom", Gender = 1, BirthDay = DateTime.Parse("2002-01-01")};将user源对象映射到为指标对象 (UserDto) var userDto = user.Adapt<UserDto>();Console.WriteLine($"映射到新对象,Name: {userDto.Name}");运行控制台程序验证转换胜利: 数据类型除了提供对象到对象的映射,还反对数据类型的转换,如: 根本类型提供类型映射的性能,相似Convert.ChangeType() string res = "123";decimal i = res.Adapt<decimal>(); //equal to (decimal)123;Console.WriteLine($"后果为:{i == int.Parse(res)}");运行控制台程序: ...

July 1, 2022 · 2 min · jiezi

关于c#:在Word文档中添加下拉列表控件-CVBNET

下拉列表是内容控件的一种,是咱们比拟罕用的一个性能。它可能限定编辑的内容,只能抉择列表里的数据录入,不便填写的同时,保障了录入数据的准确性。在微软Word中,增加控件的性能默认是敞开的,须要关上开发工具能力增加控件。但在Word文档中增加内容控件并非只能通过微软Word实现,还可通过编程实现。通过代码增加内容控件无需微软Word,同时可能集成到本人的我的项目、程序中,对于开发者来说十分不便。本文将介绍用代码实现在Word文档中增加下拉列表控件的操作方法。本文所用到的办法须要一个收费的Word库的,Free Spire.Doc for .NET,需先引入DLL文件才可在代码中援用。 1. 通过Nuget引入1.1 在Nuget治理界面中搜寻FreSpire.Doc装置。1.2 在控制台输出以下代码装置。PM> Install-Package FreeSpire.Doc 小标题2. 手动下载增加DLL拜访Free Spire.Doc for .NET官网,下载并解压文件,而后在我的项目依赖项中增加DLL文件。 在Word文档中增加下拉列表增加下拉列表的具体操作步骤如下: 创立 Document 类的对象。用 Document.LoadFromFile() 办法从磁盘载入Word文档。在文档中增加一个段落。创立内容控件。用 Paragraph.ChildObjects.Add() 办法将内容控件插入到创立的段落中。用 StructuredDocumentTagInline.SDTProperties.SDTType 属性将内容控件设置为下拉列表控件(DropDownList)。用 StructuredDocumentTagInline.SDTProperties.ControlProperties 属性增加下拉列表选项。用 StructuredDocumentTagInline.SDTContent.ChildObjects.Add() 办法设置下拉列表显示的选项。用 Document.SaveToFIle() 办法保存文档。代码示例: using System;using System.Drawing;using Spire.Doc;using Spire.Doc.Fields;using Spire.Doc.Documents;namespace AddContentControl{ internal class Program { static void Main(string[] args) { //创立Word文档 Document document = new Document(); //从磁盘加载Word文档 document.LoadFromFile(@"C:\Users\Allen\Desktop\Sample3.docx"); //在文档中增加一个段落 Section section = document.Sections[0]; Paragraph paragraph = section.AddParagraph(); TextRange text = paragraph.AppendText("下拉列表控件: "); text.CharacterFormat.FontSize = 14; text.CharacterFormat.FontName = "微软雅黑"; //创立内容控件 StructureDocumentTagInline sd = new StructureDocumentTagInline(document); //将内容控件插入到创立的段落 paragraph.ChildObjects.Add(sd); //将内容控件的类型设置为下拉列表控件 sd.SDTProperties.SDTType = SdtType.DropDownList; //增加下拉列表选项 SdtDropDownList sddl = new SdtDropDownList(); sddl.ListItems.Add(new SdtListItem("选项1")); sddl.ListItems.Add(new SdtListItem("选项2")); sddl.ListItems.Add(new SdtListItem("选项3")); sd.SDTProperties.ControlProperties = sddl; //设置下拉列表显示的选项 TextRange rt = new TextRange(document); rt.Text = sddl.ListItems[0].DisplayText; sd.SDTContent.ChildObjects.Add(rt); //保存文档 document.SaveToFile("Output.docx", FileFormat.Docx); } }}增加成果示意: ...

June 30, 2022 · 1 min · jiezi

关于c#:CVBNET-如何在Word中插入日期选择控件

微软Word提供了一个日期抉择控件的性能,不便日期数据的录入与填写。如果想要在微软Word中,增加日期抉择控件,须要当初选项中关上开发者工具,而后才能够增加日期抉择控件。如果想要将增加日期选择器的操作通过代码实现,可应用本文行将介绍的办法,通过简略的代码,无需微软Word就可在Word文档中增加日期抉择控件。本文所介绍的办法须要用到收费的Free Spire.Doc for .NET,须要先引入DLL文件。 1. 通过Nuget引入1.1 在Nuget治理界面中搜寻FreSpire.Doc装置。1.2 在控制台输出以下代码装置。PM> Install-Package FreeSpire.Doc 2. 手动下载增加DLL拜访Free Spire.Doc for .NET官网,下载并解压文件,而后在我的项目依赖项中增加DLL文件。 在一个Word文档中增加日期抉择控件增加日期抉择控件的具体操作步骤如下: 创立Word文档。用 Document.LoadFromFile() 办法从磁盘载入Word文档。在文档中增加一个段落。创立内容控件。用 Paragraph.ChildObjects.Add() 办法将内容控件插入到创立的段落中。用 StructuredDocumentTagInline.SDTProperties.SDTType 属性将内容控件设置为日期抉择控件(DatePicker)。用 SdtDate.CalendarType 属性设置日历类型。用 SdtDate.DateFormat 属性设置日期格局。用 StructuredDocumentTagInline.SDTProperties.ControlProperties 设置控件内容为日期。用 StructuredDocumentTagInline.SDTContent.ChildObjects.Add() 办法设置控件显示日期。用 Document.SaveToFile() 办法保存文档。代码示例:using System;using System.Drawing;using Spire.Doc;using Spire.Doc.Fields;using Spire.Doc.Documents;namespace AddContentControl{ internal class Program { static void Main(string[] args) { //创立Word文档 Document document = new Document(); //从磁盘加载Word文档 document.LoadFromFile(@"C:\Users\Allen\Desktop\Sample3.docx"); //在文档中增加一个段落 Section section = document.Sections[0]; Paragraph paragraph = section.AddParagraph(); TextRange text = paragraph.AppendText("日期抉择控件: "); text.CharacterFormat.FontSize = 14; text.CharacterFormat.FontName = "微软雅黑"; //创立内容控件 StructureDocumentTagInline sd = new StructureDocumentTagInline(document); //将内容控件插入到创立的段落 paragraph.ChildObjects.Add(sd); //将内容控件的类型设置为日期抉择控件 sd.SDTProperties.SDTType = SdtType.DatePicker; //设置日历类型 SdtDate date = new SdtDate(); date.CalendarType = CalendarType.Default; //设置日期格局 date.DateFormat = "yyyy.MM.dd"; //设置控件内容为日期 date.FullDate = DateTime.Now; sd.SDTProperties.ControlProperties = date; //设置控件显示日期 TextRange rt = new TextRange(document); rt.Text = "2022.06.30"; sd.SDTContent.ChildObjects.Add(rt); //保存文档 document.SaveToFile("Output.docx", FileFormat.Docx); } }}增加成果示意: ...

June 30, 2022 · 1 min · jiezi

关于c:C程序设计-09-自定义数据类型

一、定义和应用构造体变量1. 定义构造体类型后面定义应用的变量根本是互相独立、五无在分割的,在内存中的地址也是互不相干的。但在理论生存和工作中,有些数据是有内在联系的、成组呈现的。例如,一个学生的学号、姓名、性别、年龄等,是属于同一个学生的。如果将这些变量别离定义为互相独立的简略变量,难以反映他们之间的内在联系,而数组又只能寄存同一类型的数据。 C 语言容许用户本人建设又不同类型数据组成的数据结构,称为构造体(structure)。其余一些高级语言中也称为“记录”(record)。申明一个构造体类型的个别模式为: struct 构造体名 { 成员表列 };其中,struct 是申明构造体类型的关键字,不可省略。构造体名由用户指定,又称为构造体标记(structure tag),以区别于其余构造体类型。成员表列(member list)也称为域表(field list),每一个成员是构造体中的一个域。成员名命名规定与变量名雷同。构造体的成员也能够是另一个构造体。 也成为下面的例子申明构造体类型如下: struct Student { char id[10]; char name[20]; char sex; int age;}构造体类型和零碎提供的规范类型具备类似作用,都能够用来定义变量。 2. 定义构造体类型变量定义了构造体类型后,将来在程序中应用构造体类型的数据,应该定义构造体类型变量,并在其中存放数据。能够采取 3 种办法定义构造体类型变量。 先申明构造体类型,再定义该类型的变量能够应用下面定义的构造体类型 struct Student 来定义变量: struct Student student1, student2;这种模式和定义其余根本类型的变量是类似的。下面定义了 student1 和 student2 为 struct Student 类型的变量。 这种形式是申明类型和定义变量拆散,在申明类型后能够随时定义变量,比拟灵便。 在申明类型的同时定义变量这种定义方法的个别模式为: struct 构造体名 { 成员表列} 变量名表列;例如: struct Student { char id[10]; char name[20]; char sex; int age;} student1, student2;小型程序中,该办法能够间接看到构造体的构造,比拟直观不便。但在大型程序中,往往要求对构造体类型的申明和对变量的定义别离放在不同中央,以使程序结构清晰,便于保护。 不指定类型名而间接定义构造体类型变量其个别模式为: struct { 成员表列} 变量名表列;该办法指定了一个无名的构造体类型,因为没有构造体名,因而不宜再次以此构造体类型去定义其余变量。 ...

June 30, 2022 · 5 min · jiezi

关于c:C程序设计-08-指针

一、什么是指针1. 地址与指针在程序中定义了一个变量,编译时零碎会给这个变量调配存储单元,同时依据变量的数据类型,调配肯定长度的空间。内存区的每一个字节都有一个编号,这就是“地址”。因为通过地址就能够找到所需的变量单元,能够说,地址指向该变量单元。由此,将地址形象地称为指针。 C 语言对不同的数据类型调配不同大小的存储单元,且不同数据类型的存储形式是不一样的。因而,即便给了一个地址,也无奈保障能正确存取所须要的信息。为了能正确存取一个数据,前途须要地位信息,还须要该数据的类型信息。C 语言的地址包含地位信息(地址编号,或称纯地址)和它所指向的数据的类型信息,或者说它是“带类型的地址”。 2. 间接拜访与间接拜访在程序中,个别是通过变量名来援用变量的值的,如: scanf("%d", &n);printf("%d\n", n);这种间接按变量名进行的拜访称为间接拜访。 还能够采纳另一种称为间接拜访的形式,行将一个变量 n 的地址寄存在另一个变量 n_pointer 中,而后通过变量 n_pointer 来找到变量 n 的地址,从而拜访该变量。 如果咱们要对变量 n 赋值,当初就有了两种办法: 间接拜访:依据变量名间接向变量 n 赋值,因为变量名与变量地址有一一对应关系,因而就依照此地址间接对变量 n 的存储单元进行拜访。间接拜访:先找到寄存变量 n 地址的变量 n_pointer,从中失去变量 n 的地址,从而找到变量 n 的存储单元,对它进行拜访。如果一个变量专门用来寄存另一变量的地址,则称为指针变量。上述的 n_pointer 就是一个指针变量。指针变量就是地址变量,用来寄存地址。 二、指针变量寄存地址的变量就是指针变量,它用来指向另一个对象(如变量、数组、函数等)。 1. 定义指针变量定义指针变量的个别模式为: 类型名* 指针变量名;定义指针是必须指定其根本类型,该类型示意此指针能够指向的变量的类型。因而,指针类型是根本数据类型派生进去的类型,不能来到根本类型而独立存在。 定义指针的同时也能够对其进行初始化,如: int* a;char* b = &c;定义指针时要留神: 指针后面的 * 示意该变量为指针型变量,指针变量名为 a 而不是 *a。一个变量的指针的含意包含两方面:存储单元编号示意的地址和它指向的存储单元的数据类型。指针变量只能寄存地址,不能将一个整数赋值给指针变量。2. 援用指针变量援用指针变量有 3 种状况: 给指针变量赋值: p = &a;援用指针变量指向的变量: *p = 1;printf("%d", *p);援用指针变量的值: printf("%o", p); // 以八进制输入指针变量的值(即指向的变量的地址)要熟练掌握两个无关运算符: &:取地址运算符。*:指针运算符(或称为“间接拜访运算符”)。3. 指针变量作为函数参数将一个变量的地址传到一个函数中能够应用指针变量作为函数参数。 ...

June 30, 2022 · 5 min · jiezi

关于c++:VS2022-win10编译SFML26

之前写过一篇Clion配置C++/SFML开发环境(Win10),因为Clion是免费的IDE,收费的IDE目前靠谱的抉择只有Visual Studio,因而再写一篇基于Visual Studio 2022的教程。因为SFML未提供编译好的基于Visual Studio 2022的版本,因而这里须要本人编译。 环境操作系统: windows 10 版本 1909 (外部版本 18363.1646)IDE: Microsoft Visual Studio Community 2022 (64 位) 版本 17.2.5CMake: cmake-gui 3.24.0-rc2SFML: 2.6.x (Github源码编译)步骤从Github下载2.6.x分支的SFML源码关上CMake-gui,如图所示,抉择下载好SFML源代码目录,任意设置一个build目录,而后点击Configure 抉择Visual Studio 2022作为generator,点击Finish 此时Configure开始执行,执行完(Configuring done)成会呈现红色的参数须要设置,如下图所示,个别都不必改,我这里把CMAKE_INSTALL_PREFIX改成另一个指定的目录,而后再次点击Configure 第二次Configure实现之后,不再有红色参数,点击旁边的Generate,执行实现后,点击Open Project 此时会关上Visual Studio 2022,执行INSTALL -> 生成,即可把SFML装置在指定的目录。 通过Visual Studio 2022再新建一个CMake我的项目,CMakeLists.txt内容如下 cmake_minimum_required (VERSION 3.8) project("SFML2048") # 设置SFML目录 set(SFML_DIR "D:\\Program Files\\SFML\\lib\\cmake\\SFML") find_package(SFML REQUIRED COMPONENTS audio network graphics window system) if (NOT SFML_FOUND) message(FATAL_ERROR "SFML NOT FOUND!") else() message("SFML FOUND!") endif() include_directories(${SFML_INCLUDE_DIR}) add_executable (SFML2048 "SFML2048.cpp" "SFML2048.h") if (CMAKE_VERSION VERSION_GREATER 3.12) set_property(TARGET SFML2048 PROPERTY CXX_STANDARD 20) endif() target_link_libraries("SFML2048" sfml-main sfml-audio sfml-network sfml-graphics sfml-window sfml-system) # 把DLL复制到执行目录 set( DLL_FILES "D:\\Program Files\\SFML\\bin\\sfml-graphics-2.dll" "D:\\Program Files\\SFML\\bin\\sfml-window-2.dll" "D:\\Program Files\\SFML\\bin\\sfml-system-2.dll" ) foreach(DLL_FILE ${DLL_FILES}) message("Found DLL to Copy: ${DLL_FILE}") add_custom_command( TARGET SFML2048 PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${DLL_FILE} ${CMAKE_BINARY_DIR}. ) endforeach()测试以下代码,执行胜利将绘制一个绿色的圆 ...

June 29, 2022 · 1 min · jiezi

关于c++:C-explicit-用法

引言本文介绍了 C++ 中 explicit 关键字的用法. 原文地址: C++ explicit 用法 欢送拜访我的博客: http://blog.duhbb.com/ explicit 作用在 C++中, explicit 关键字用来润饰类的构造函数, 被润饰的构造函数的类, 不能产生相应的隐式类型转换, 只能以显式的形式进行类型转换. explicit 应用注意事项: explicit 关键字只能用于类外部的构造函数申明上.explicit 关键字作用于单个参数的构造函数 (多个参数也实用, 但必须只有一个参数须要赋值, 其余的参数有默认值).在 C++ 中, explicit 关键字用来润饰类的构造函数, 被润饰的构造函数的类, 不能产生相应的隐式类型转换.it cannot be used for implicit conversions and copy-initialization多个参数的状况其实对于下面的第二点我是存疑的, 因为 CPP Reference explicit specifier 中的例子表明 explicit 是能够用于多个参数的. 例子例 1 根底例子#include <bits/stdc++.h>using namespace std;class Test1 {public: Test1(int n) { m_num = n; }private: int m_num;};class Test2 {public: explicit Test2(int n) { m_num = n; }private: int m_num;};int main() { Test1 t1 = 12; // 隐式调用构造函数胜利 Test2 t2 = 12; // 编译谬误, 不能隐式调用其构造函数 Test2 t2(12); // 显式调用胜利 return 0;}例 2 CPP Reference 中的例子上面是 CPP Reference explicit specifier 中的例子, 感觉更全面一点: ...

June 28, 2022 · 2 min · jiezi

关于c#:NET-如何在Word中插入组合框Combo-Box

组合框(Combo Box)是文本框和下拉列表的组合,同时容许编辑者在列表抉择我的项目显示和输出内容。它是Word文档中一个十分实用的性能,对于比拟固定的一些数据,如性别、地点,或是几个我的项目的抉择等,用组合框就能够不便数据录入,又容许对于数据的增加。增加组合框可通过代码实现,无需微软Word或是其余文档编辑软件,可将代码集成到本人的程序中实现该性能。本文将介绍通过代码实现增加组合框到Word文档中的操作方办法。本文所介绍的办法须要借助收费Word库Free Spire.Doc for .NET,需引入DLL文件以及插件到我的项目中应用。 1. 通过Nuget引入1.1 在Nuget治理界面中搜寻FreSpire.Doc装置。1.2 在控制台输出以下代码装置。PM> Install-Package FreeSpire.Doc 2. 手动下载增加DLL在Free Spire.Doc for .NET官网下载解压文件,而后在我的项目依赖项中增加DLL文件。 在Word文档中插入组合框具体操作步骤如下: 通过创立 Document 类的对象创立Word文档。用 Document.LoadFromFile() 办法从磁盘加载Word文档。用 Section.AddParagraph() 办法在文档第一节中增加一个段落。在增加的段落中增加文字并设置字号、字体。通过创立 StructureDocumentTagInline 的对象创立内容控件。用 Paragraph.ChildObjects.Add() 办法将内容控件插入到定位的段落。用 SdtType.ComboBox 属性将内容控件的类型设置为组合框。通过创立 SdtComboBox 的对象创立组合框控件。用 SdtComboBox.ListItems.Add() 办法设置组合框控件的选项。f用 SdtComboBox.ListItem[].DisplayText 属性抉择下拉列表第二个选项,并用 SDTContent.ChildObjects.Add(rt) 办法将该选项增加为显示的选项。用 Document.SaveToFile() 办法保存文档。代码示例: using System;using System.Drawing;using Spire.Doc;using Spire.Doc.Fields;using Spire.Doc.Documents;namespace AddContentControl{ internal class Program { static void Main(string[] args) { //创立Word文档 Document document = new Document(); //从磁盘加载Word文档 document.LoadFromFile(@"C:\Users\Allen\Desktop\New Microsoft Word Document (2).docx"); //在文章第一节中增加一个段落 Section section = document.Sections[0]; Paragraph paragraph = section.AddParagraph(); //在增加的段落中增加文字并设置字号、字体 TextRange text = paragraph.AppendText("组合框控件: "); text.CharacterFormat.FontSize = 14; text.CharacterFormat.FontName = "微软雅黑"; //创立内容控件 StructureDocumentTagInline sd = new StructureDocumentTagInline(document); //将内容控件插入到创立的段落 paragraph.ChildObjects.Add(sd); //将内容控件的类型设置为组合框 sd.SDTProperties.SDTType = SdtType.ComboBox; //创立组合框控件 SdtComboBox cb = new SdtComboBox(); //设置组合框控件的选项 cb.ListItems.Add(new SdtListItem("A")); cb.ListItems.Add(new SdtListItem("B")); cb.ListItems.Add(new SdtListItem("C")); //将组合框控件插入到后面创立的内容控件 sd.SDTProperties.ControlProperties = cb; //将组合框控件设置为显示第二个选项 TextRange rt = new TextRange(document); rt.Text = cb.ListItems[1].DisplayText; sd.SDTContent.ChildObjects.Add(rt); //保存文档 document.SaveToFile("Output.docx", FileFormat.Docx); } }}增加成果示意: ...

June 28, 2022 · 1 min · jiezi

关于c++:C头文件-bitsstdch-是啥

原文地址: 【C++】头文件 bits/stdc++.h 是啥? 欢送拜访我的博客:http://blog.duhbb.com/ 嘿嘿, 当前写 leetcode 的话, 本地间接就援用这个文件, 还是很不便的;然而因为不可移植以减少编译工夫等, 墙裂倡议不要在生产环境应用. 引言最近看他人的 C++ 代码, 发现了这么一个头文件: #include <bits/stdc++.h>而后我就有点奇怪了, 以前如同没有遇到过呀, 而后这个 C++ 头文件也比拟特地, 是以 .h 结尾的, 于是乎打算一探到底. 它是 C++ 中反对的一个简直万能的头文件, 简直蕴含所有的可用到的 C++ 库函数. 当前写代码就能够间接援用这一个头文件了, 不须要在写一大堆 vector, string, map, stack 等等 应用办法#include <bits/stdc++.h>int main() { // write code here return 0}头文件的内容// C++ includes used for precompiling -*- C++ -*-// Copyright (C) 2003-2013 Free Software Foundation, Inc.//// This file is part of the GNU ISO C++ Library. This library is free// software; you can redistribute it and/or modify it under the// terms of the GNU General Public License as published by the// Free Software Foundation; either version 3, or (at your option)// any later version.// This library is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.// Under Section 7 of GPL version 3, you are granted additional// permissions described in the GCC Runtime Library Exception, version// 3.1, as published by the Free Software Foundation.// You should have received a copy of the GNU General Public License and// a copy of the GCC Runtime Library Exception along with this program;// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see// <Licenses - GNU Project - Free Software Foundation>./** @file stdc++.h * This is an implementation file for a precompiled header. */// 17.4.1.2 Headers// C#ifndef _GLIBCXX_NO_ASSERT#include <cassert>#endif#include <cctype>#include <cerrno>#include <cfloat>#include <ciso646>#include <climits>#include <clocale>#include <cmath>#include <csetjmp>#include <csignal>#include <cstdarg>#include <cstddef>#include <cstdio>#include <cstdlib>#include <cstring>#include <ctime>#if __cplusplus >= 201103L#include <ccomplex>#include <cfenv>#include <cinttypes>#include <cstdalign>#include <cstdbool>#include <cstdint>#include <ctgmath>#include <cwchar>#include <cwctype>#endif// C++#include <algorithm>#include <bitset>#include <complex>#include <deque>#include <exception>#include <fstream>#include <functional>#include <iomanip>#include <ios>#include <iosfwd>#include <iostream>#include <istream>#include <iterator>#include <limits>#include <list>#include <locale>#include <map>#include <memory>#include <new>#include <numeric>#include <ostream>#include <queue>#include <set>#include <sstream>#include <stack>#include <stdexcept>#include <streambuf>#include <string>#include <typeinfo>#include <utility>#include <valarray>#include <vector>#if __cplusplus >= 201103L#include <array>#include <atomic>#include <chrono>#include <condition_variable>#include <forward_list>#include <future>#include <initializer_list>#include <mutex>#include <random>#include <ratio>#include <regex>#include <scoped_allocator>#include <system_error>#include <thread>#include <tuple>#include <typeindex>#include <type_traits>#include <unordered_map>#include <unordered_set>#endif长处与毛病起源: bits/stdc++.h in C++ ...

June 27, 2022 · 2 min · jiezi

关于c:替换百度云这款开源网盘颜值更高功能更全面

你好,我是小金。 如果你还在纠结应用什么工具来存储文件,还在放心文件的内容不平安,还在因为云存储服务(比方百度云)的托管费用以及下载速度而不悦的话,请肯定要看完小金明天举荐的开源云盘我的项目。 说不定!这个我的项目就会成为你的所爱。 这个开源笔记我的项目就是 Seafile,一个一款平安、高性能的开源网盘,基于 C 语言开发而成,不论是自用还是搭建企业云盘都十分不错! Seafile 提供了支流网盘(云盘)产品所具备的性能,包含文件同步、文件共享、合作共享、Office 文档在线编辑、Wiki 与常识治理等。 成果预览上面咱们来简略看看应用 Seafile 搭建的在在线云盘的效果图。 跨平台文件同步 挪动端文件拜访 挂载盘客户端 不必同步即可像本地磁盘一样拜访云端文件。 在线编辑和协同编辑 Wiki 与常识治理 装置应用Seafile 是开源的,你能够把它部署在公有云的环境中,作为公有的企业网盘。Seafile 反对 Mac、Linux、Win­dows 三个桌面平台,反对 An­droid 和 iOS 两个挪动平台。 装置部署 Seafile 的教程:https://manual.seafile.com/build_seafile/server 。 如果你本人部署我的项目的话,能够间接应用 Seafile 官网提供的 SaaS 服务。你只须要注册一个账号,即可在云上应用多终端文件同步、合作共享、Office 文档在线编辑、全文检索、常识治理等 Seafile 企业版性能。 总结Seafile 提供了支流网盘(云盘)产品所具备的性能,包含文件同步、文件共享、合作共享、Office 文档在线编辑等。 如果你或者你的团队须要搭建一个在线云盘应用的话,能够考虑一下这个我的项目。 我的项目地址: https://github.com/haiwen/seafile

June 27, 2022 · 1 min · jiezi

关于c:C语言的文件操作

文件分类程序文件:源程序文件(.c文件)、指标文件(.obj文件)、可执行文件(.exe文件)数据文件:程序运行时读写的数据。文件的关上和敞开文件类型指针文件在被关上时,都会在内存中开拓一个相应的文件信息区,用来寄存被关上文件的相干信息(文件名、文件大小、文件地位等)。这些信息是保留在一个构造体中的,该构造体的申明就是FILE类型。 FILE *fptr; //文件指针 fptr = fopen("runoob.txt", "r")) //fopen关上一个文件,返回一个 FILE 指针 //fptr 当初就指向 runoob.txt文件的文件信息区。文件的关上和敞开在关上文件时,都会返回一个FILE* 的指针变量指向该文件,这样就建设了指针和文件的关系。留神:关上文件后,必须敞开文件,并且将定义的文件指针赋值为NULL。ANSIC规定:应用 fopen 函数来关上文件,应用 fclose 函数来敞开文件FILE *fopen(const char *filename, const char *mode) //关上文件函数//filename:字符串,示意要关上的文件名称//mode :字符串,示意文件的拜访模式,//返回值 :关上胜利返回一个 FILE 指针。否则返回 NULLint fclose(FILE *stream) //敞开文件函数//如果胜利敞开,则该办法返回零。如果失败,则返回 EOF。mode 文件拜访模式可选的值:文件的程序读写fgetc :字符读取函数(实用于所有流)fputc :字符写入函数(写入单个字符)fgets :文本行读取函数(从文件中读取一整行数据)fputs :文本行写入函数fscanf :格式化读取函数(从文件中读取数据)fprintf :格式化写入函数(向文件中写入数据)fread :二进制读取(实用于文件)fwrite :二进制写入(实用于文件)scanf/fscanf/sscanf和printf/fprintf/sprintf区别scanf :格式化的输出函数(输出就是读取,程序向控制台读取数据)printf :格式化的输入函数(输入就是写入,程序向控制台写入数据)fscanf :针对所有输出流的格式化输出函数fprintf :针对所有输入流的格式化输入函数sscanf :把一个字符串转换为格式化的数据sprinft :把一个格式化数据转换成字符串指定文件的地位读写fseek重定位指针依据文件指针的地位(whence)和偏移量(offset)来重定位文件指针(stream)int fseek(FILE *stream, long int offset, int whence)stream : 这是指向 FILE 对象的指针。offset : 这是绝对 whence 的偏移量,以字节为单位。whence : 指定文件指针的初始地位 SEEK_SET :文件的结尾SEEK_CUR :文件指针的以后地位SEEK_END :文件的开端#include <stdio.h>int main (){ FILE *fp; fp = fopen("file.txt","w+"); //创立一个用于写入的空文件 fputs("This is runoob.com", fp); //向文件中写入内容 fseek( fp, 7, SEEK_SET ); //重定位文件指针 fputs(" C Programming Langauge", fp); //向重定位后的地位写入数据 fclose(fp); //敞开文件 return(0);}//运行后果:This is C Programming Langaugeftell查找以后文件指针地位long int ftell(FILE *stream)stream :以后文件指针返回值 :返回以后文件指针相当于文件起始地位的偏移量rewind设置指针地位为文件起始地位void rewind(FILE *stream)函数作用:使文件指针stream指向文件的起始地位。被谬误应用的feof函数这个函数不能用来判断文件是否读取完结。而是用来在文件读取完结后,判断是哪种形式导致的文件读取完结(是文件读取失败还是文遇到文件结尾而完结的)文件缓冲区零碎会主动在内存中为每一个正在应用的文件开拓一块文件缓冲区(是在内存中开拓的)从程序向磁盘写入数据时,数据会先传输到缓冲区,当缓冲区填充斥后,再一起传输到硬盘中。从硬盘读取数据到程序时,数据也会先传输到缓冲区,当缓冲区填充斥后,再一起传输到内存中。fclose在敞开文件时,也会将缓冲区残余的数据放到硬盘中。

June 24, 2022 · 1 min · jiezi

关于c:动态内存管理

动静开拓内存malloc开拓内存#include <stdlib.h>void *malloc(size_t size)size :须要开拓的内存空间的大小,以字节为单位。返回值 :返回一个指向开拓的内存空间的指针(void*类型,须要其余类型时应用强制类型转换即可)如果申请失败,则返回 NULL。free开释空间void free(void *ptr)函数作用:开释之前调用 calloc、malloc 或 realloc 所调配的内存空间。ptr:指针指向一个要开释内存的内存块。个别在开释空间时,同时也会将该空间的指针赋值为NULL,防止它成为野指针。如果不开释申请的内存空间,在程序完结时,会由操作系统主动回收。calloc开拓内存malloc 和 calloc 之间的不同点是:calloc 会将申请的空间初始化为0,而malloc 是随机值。void *calloc(size_t nitems, size_t size)nitems :要被调配的元素个数。size :元素的大小。如果申请失败,则返回 NULL。realloc从新分配内存void *realloc(void *ptr, size_t size)ptr :须要从新分配内存的内存块的指针。 该内存块之前是通过调用 malloc、calloc 或 realloc 进行分配内存的。如果为空指针,则会调配一个新的内存块。size : 内存块的新的大小,以字节为单位。 如果大小为 0,且 ptr 指向一个已存在的内存块,则 ptr 所指向的内存块会被开释,并返回一个空指针。留神: 如果源内存前面的空间足够大,则realloc会在源空间前面追加分配内存。如果源内存前面的空间不够大,则realloc会在其余空间分配内存,并且将原来空间的值顺次拷贝过来,而后将原来的空间开释掉。常见的动态内存谬误对NULL指针的解援用操作int main(){ int* p = (int*)malloc(1000); *p = 10; //如果内存调配失败,malloc返回NULL,这里就会出错 return 0;}解决办法:进行NULL检测(判断malloc(1000)是否等于NULL)对动静开拓空间的越界拜访int* p = (int*)malloc(1000);for (int i = 0;i<1000;i++){ *(p + i) = i; //这里当i超过250后,就会呈现越界拜访}对非动静开拓内存的开释int a = 10;int* p = &a;free(p); //a是局部变量,不能用free开释,由零碎主动开释p = NULL;对动静开拓的空间只开释一部分int* p = (int*)malloc(100);for (int i = 0; i < 50; i++){ p++;}free(p); //此时指针p曾经指向开拓的空间两头局部了,只能开释指针之后的局部p = NULL;对同一块内存屡次开释int* p = (int*)malloc(100);free(p); p = NULL;free(p); //屡次开释,程序会出错。p = NULL;

June 23, 2022 · 1 min · jiezi

关于c:通讯录小项目实现增删改查

main.c文件#define _CRT_SECURE_NO_WARNINGS 1#include "contact.h"void test(SUM* pc){ /*char arr[] = "222"; change(pc,arr); print(pc);*/ int i = 0; char arr[name_MAX]; printf("请输出指令:"); while (1) { scanf("%d", &i); switch (i) { case ADD_1: ADD(pc); printf("请再次输出指令:"); break; case delet_2: printf("请输出要删除的联系人姓名:"); scanf("%s", arr); delet(pc, arr); printf("请再次输出指令:"); break; case change_3: printf("请输出要批改的联系人姓名:"); scanf("%s", arr); change(pc, arr); printf("请再次输出指令:"); break; case search_4: printf("请输出要搜寻的联系人姓名:"); scanf("%s", arr); print_one(pc, search(pc, arr)); printf("请再次输出指令:"); break; case print_5: print(pc); printf("请再次输出指令:"); break; case print_one_6: printf("请输出要显示的联系人姓名:"); scanf("%s", arr); print_one(pc, search(pc, arr)); printf("请再次输出指令:"); break; default: printf("输出有误!请从新输出:"); break; } } return;}int main(){ //构造体初始化 SUM Data = { .people = {{"111","444","777"},{"222","555","888"},{"333","666","999"}}, .size = 3 }; test(&Data); return 0;}contact.c文件#define _CRT_SECURE_NO_WARNINGS 1#include "contact.h"//减少联系人void ADD(SUM* const pc){ printf("请输出姓名:"); scanf("%s", &(pc->people[pc->size].name)); printf("请输出单位:"); scanf("%s", &(pc->people[pc->size].danwei)); printf("请输出号码:"); scanf("%s", &(pc->people[pc->size].tele)); (pc->size)++; return;}//搜寻联系人,依据姓名查找,返回对应的下标int search(SUM* const pc, const char * arr){ for (int i = 0;i<pc->size;i++) { if (strcmp(((pc->people)[i].name), arr) == 0) { return i; //找到了,返回对应下标 } } return -1; //-1示意没找到}//删除联系人void delet(SUM* const pc, const char *arr){ int a = search(pc,arr); for (a;a<(pc->size-1);a++) { pc->people[a] = pc->people[a + 1]; } (pc->size)--; return;}//打印联系人void print(SUM* const pc){ for (int i = 0; i < pc->size; i++) { printf("%s ", (pc->people)[i].name); printf("%s ", (pc->people)[i].danwei); printf("%s ", (pc->people)[i].tele); printf("\n"); } return;}//打印某一个联系人void print_one(SUM* const pc, const int i){ printf("%s ", (pc->people)[i].name); printf("%s ", (pc->people)[i].danwei); printf("%s ", (pc->people)[i].tele); printf("\n"); return;}//改void change(SUM* const pc, const char* arr){ int a = search(pc, arr); printf("请输出姓名:"); scanf("%s",pc->people[a].name); printf("请输出单位:"); scanf("%s", pc->people[a].danwei); printf("请输出号码:"); scanf("%s", pc->people[a].tele); return;}contact.h文件#pragma once#include <stdio.h>#include <string.h>#define name_MAX 20#define danwei_MAX 20#define tele_MAX 12#define people_MAX 100#define ADD_1 1#define delet_2 2#define change_3 3#define search_4 4#define print_5 5#define print_one_6 6typedef struct Contact{ char name[name_MAX]; char danwei[danwei_MAX]; char tele[tele_MAX];}Contact;typedef struct SUM{ Contact people[people_MAX]; int size;}SUM;void ADD(SUM* const pc);void delet(SUM* const pc, const char* arr);void change(SUM* const pc, const char* arr);int search(SUM* const pc, const char* arr);void print(SUM* const pc);void print_one(SUM* const pc, const int i);

June 23, 2022 · 2 min · jiezi

关于c#:CVBNET-把网页文件HTML转换为PDF文档

HTML(超文本标记语言)是一种罕用于展现网页的标记语言,而HTML文件则是这种标记语言所对应的文件格式,绝大多数网页文件都采纳这种格局。但HTML文件在不同设施、不同平台上,可能呈现排版展现成果不同的问题。如果咱们想让文件展现出的页面保持一致,可将其转换为PDF文件进行保留和传输。本文介绍一种十分不便的办法,通过简略编程实现HTML文件转换为PDF文件。也可将这种转换方法集成到别的程序中,使程序实现转换性能。此办法需应用收费的Free Spire.PDF for .NET,需援用DLL文件到我的项目中应用。 1. 通过Nuget装置1.1 在Nuget治理界面中搜寻FreSpire.PDF装置。1.2 在控制台输出以下代码装置。PM> Install-Package FreeSpire.Doc 2. 手动下载增加DLL在Free Spire.PDF for .NET官网下载解压文件,而后在我的项目依赖项中增加DLL文件。 将一个HTML文件转换为PDF文件转换的具体操作步骤如下: 创立 PdfDocument 类的对象。用 PdfDocument.LoadFromHTML() 办法从url加载HTML文件。用 PdfDocument.SaveToFile() 办法保留为PDF文件。代码示例://创立PdfDocument类的对象PdfDocument doc = new PdfDocument();//从URL加载HTML文件String url = "https://www.baidu.com/";Thread thread = new Thread(() =>{ doc.LoadFromHTML(url, false, true, true); });thread.SetApartmentState(ApartmentState.STA);thread.Start();thread.Join();//保留为Pdf文件doc.SaveToFile("sample.pdf");转换成果示意: 以上代码中援用的代码均来自收费的Free Spire.PDF for.NET。

June 23, 2022 · 1 min · jiezi

关于c:自定义类型结构体等

构造体构造体定义方法定义方法一: struct MyStruct //定义构造体,定义的构造体在内存中是不占空间的{ int a; char b; short c;}; //没有创建对象int main(void){ //应用构造体,创立一个构造体对象,创建对象时才会占用内存空间 struct MyStruct a = {10,'b',4}; //能够在创立时就初始化,也能够在之后赋值 struct MyStruct* sp = &a; //构造体指针 a.a = 10; (*sp).b = 'b'; sp->c = 4;}定义方法二: struct MyStruct{ int a; char b; short c;}s1,s2,s3; //s1,s2,s3 是创立的构造体对象,在定义构造体的同时创建对象//s1,s2,s3 是全局变量 int main(void){ s1.a = 10; //这里能够间接应用构造体对象}定义方法三: typedef struct MyStruct //相当于对这个构造体重命名为 Stu{ int a; char b; short c;}Stu; int main(void){ Stu s1; //应用重命名,进行创建对象。}构造体作为参数时函数传参时,参数是须要压栈的如果传递一个构造体对象时,间接传递构造体实参,在函数那边会压栈一个同样大小的内存空间(创立构造体形参),会导致系统开销增大,从而导致性能升高。所以传递构造体参数时,尽量传递构造体的指针(地址)匿名构造体类型留神:如果两个匿名构造体的成员一样,然而在编译器看来也是不同的构造体类型。struct //没有申明构造体的名称{ int a; char b; short c; }x; //定义了一个构造体的对象//这种申明构造体办法,只能在申明时定义构造体对象,之后不能在定义对象(没有构造体名称)struct { int a; char b; short c; }p; //p和x是不同的构造体类型。构造体的自援用struct Node{ int date; struct Node* next; //用指针指向下一个同类构造体的地址。 //struct Node n; //在构造体中创立本人类型的对象 //这种用法是谬误的,会呈现套娃的状况,内存会无限大,零碎报错}构造体内存对齐先看示例:struct X { int a; char b; short c; }; struct P { char a; int b; char c short d; struct X st;}; struct P a;printf("%d\n",sizeof(p)); //输入后果为 20构造体对齐规定第一个成员,寄存在构造体变量偏移量为0的地址处(即构造体变量的首地址处)其余成员要对齐到某个数(对齐数)的整数倍的地址处。 ...

June 22, 2022 · 2 min · jiezi

关于c:字符串和内存函数

字符操作函数strlen()求字符串长度#include <string.h>size_t strlen(const char *str)str :要计算长度的字符串的首地址。size_t :这是unsigned int类型,是无符号的。留神 :必须读取到 \0 才算完结,然而返回的长度不包含结尾字符 \0。char arr1[] = "abcd";char arr2[] = {'a','b','c','d'};int a = strlen(arr1); //a的值为4int c = strlen(arr2); //c的值无奈确认,因为数组前面没有\0,所以strlen要始终计算到有 \0的中央才完结//所以C的值可能会很大字符串拷贝strcpy()#include <string.h>char *strcpy(char *dest, const char *src)把 src 所指向的字符串复制到 dest。该函数返回一个指向最终的指标字符串 dest 的指针(即返回dest的地址)留神:源字符串 src 必须以 \0 结尾,否则程序会解体这个函数会将源字符串中的 \0 也拷贝过来。留神:指标dest空间的值必须可变,能力放下源字符串。char* arr1 = "abcde";char arr2[] = "qwer";strcpy(arr1,arr2); //这种用法是谬误的,程序会解体// 因为arr1 是常量字符串,是不可更改的,所以会解体。strncpy()char *strncpy(char *dest, const char *src, size_t n)n :指定要从 src 中拷贝的字符个数。当源字符串 src 中没有 n 个字符时,任然会拷贝 n 个字符(残余的用 '\0' 填充)字符串追加strcat()#include <string.h>char *strcat(char *dest, const char *src)作用:将src中的字符串追加到 dest 字符串前面。dest :指向指标数组,该数组蕴含了一个 C 字符串,且足够包容追加后的字符串。src :指向要追加的字符串,该字符串不会笼罩指标字符串。返回值:返回一个指针,指向dest。这种办法追加字符串,能够追加本人。留神: ...

June 22, 2022 · 2 min · jiezi

关于c:函数指针

函数指针函数指针:指向函数的指针,函数名就相当于一个函数指针。函数指针的定义int add(int a,int b){ return a+b;}int main(){ printf("%p", add); printf("%p", &add); //两个输入后果雷同,add和&add都是失去函数的地址 int (*pf)(int, int) = add; //定义函数指针 //(*pf)示意变量pf是一个指针,(int, int)示意函数的参数类型,int 示意函数的返回值}函数指针的应用int (*pf)(int, int) = add; //定义函数指针int ret = (*pf)(2,3);//(2,3)示意传递的参数,(*pf)解援用函数,调用函数,留神这个括号不能省略。int ret = pf(2,3); //pf其实就相当于add。简单函数指针类型解读(*(void(*)())0)();//首先最内层:(*)示意它是一个指针//其次:void(*)() 这是一个定义函数指针的变量类型,返回值为void,无传参。//(void(*)())0 变量类型被放在括号中,示意强制类型转换,将0转化为函数指针,这示意0地址处寄存的是一个函数地址//*(void(*)())0 解援用这个函数指针,调用函数//(*(void(*)())0)() 最初的括号示意函数传参。//这句程序的作用是:调用0地址处的函数void (*add(int,void(*)(int)))(int);//首先最内层:void(*)(int) 示意一个函数指针类型//其次:add(int,void(*)(int)) ;add示意函数名,(int,void(*)(int))示意这个函数的参数//当去掉add(int,void(*)(int))之后,只剩下void (*)(int),而void (*)(int)就是函数的返回类型//所以这句程序的意思:定义一个函数,函数名为add,传参为(int,void(*)(int)),返回值为void (*)(int)型//其实就相当于:void (*)(int) add(int,void(*)(int)) //然而留神下面这个写法是错的,只是能够这样了解上述程序。//能够应用另外一种办法实现上述程序typedef void(*pf_t)(int) ; //重定义类型,将void(*)(int)类型用pf_t代替pf_t add(int, pf_t); //这句成果和上述程序雷同。函数指针数组int (*p[3])(int,int) = {test1,test2,test3}; //定义函数指针数组p[3]。int ret = p[1](3,5); //应用函数指针数组指向函数指针数组的指针int (*pf[4])(int, int); //函数指针数组//pf先与[4]联合示意它是一个数组int (*(*p)[4])(int, int) = &pf; //指向函数指针数组的指针//p先与*号联合,示意它是一个指针int ret = (*p)[1](3,4); //指向函数指针数组的指针的应用//(*p)先解援用失去函数指针数组,(*p)就相当于pf,[1]示意应用第哪个函数,(3,4)示意传参。C库排序函数qsort()它不仅只能排序数组,还能够排序构造体等void qsort(void *base, size_t nitems, size_t size, int (*compar)(const void *, const void*))//base -- 指向要排序的数组的第一个元素的指针。//nitems -- 要排序数组中元素的个数.//size -- 数组中每个元素的大小,以字节为单位//compar -- 用来比拟两个元素的函数,这个函数须要程序员本人依据理论状况写//compar 函数只须要比拟第一个参数和第二个参数的大小并返回即可//返回值为正,则示意正序排列//返回值为负,则示意反序排列//返回值为0, 示意不排序示例:输入后果:15 20 24#define _CRT_SECURE_NO_WARNINGS 1#include <stdio.h>#include <stdlib.h>struct Stu{ char name[10]; int age; double score;};int compar(const void* e1, const void* e2){ return ((struct Stu*)e1)->age - ((struct Stu*)e2)->age;}void main(){ struct Stu arr[3] = { {"zhangsan",20,55.5},{"lishi",24,57.0},{"wangwu",15,34.2} }; int sz = sizeof(arr) / sizeof(arr[0]); //计算要排序数组中元素的个数 qsort(arr, sz, sizeof(arr[0]), compar); for (int i = 0; i < 3; i++) { printf("%d\n", arr[i].age); }}

June 20, 2022 · 1 min · jiezi

关于c:数组与指针二

数组和指针传参一维数组传参int arr[10] = {0};test(arr); //实参传递的是数组的首元素首地址//形参写成数组的模式 void test(int brr1[10]) //办法一void test(int brr1[]) //办法二,形参局部能够省略数组大小。void test(int brr1[100]) //办法三,也能够将数组大小写得很大,然而不倡议//形参的[]中的数字并没有意义//int brr1[],变量brr1就是int* 类型,理论形参还是个指针,跟上面的指针形参是一样的。//形参写成指针的模式void test(int *p1);指针数组传参int* arr2[10] = {0};test2(arr2); //arr2是二重指针类型int**。void test2(int* brr2[10]);void test2(int* brr2[]);void test2(int** p2); //形参为二重指针二维数组传参int arr3[3][5] = {0};test3(arr3); //arr3是int(*)[5]类型,即一维数组指针类型,传递的是第一行数组的地址void test3(int brr3[3][5]);void test3(int brr3[][5]); //行能够不写,然而列必须写对。void test3(int (*p3)[5]); //留神这个[]的5必须写//形参为指针模式时,类型也要为数组指针类型int(*)[5]test3(&arr); //传递的是整个二维数组的地址,int(*)[3][5]类型,即二维数组指针类型。void test3(int(*p)[3][5]);一重指针传参int arr4[10] = {1,2,3,4,5,6,7,8,9,10};int* p4 = arr; //p4指向 数组首元素1的地址。test(p4);void test(int* ptr); //形参为指针模式,传递一重指针。int arr4[10] = {1,2,3,4,5,6,7,8,9,10};int* p4 = arr; //p4指向 数组首元素1的地址。test(p4);void test(int* ptr); //形参为指针模式,传递一重指针。二重指针传参int a = 10;int* pa = &a;int** ppa = &pa;test5(ppa); //实参为二重指针void test5(int** ptr); //形参也要为二重指针

June 20, 2022 · 1 min · jiezi

关于c:C语言中数据的存储

整数在内存的存储形式符号位用0示意正,1示意负。整数在内存中是以补码的模式保留的(负数的源反补码雷同,正数的源反补码不同)留神:变量类型在读取时会有一个整形晋升的问题 整形晋升在存储变量时是没有的,只在读取时存在例如:char类型的数,输入的用%d整形输入。整形晋升时,有符号类型依据首位进行补位,无符号类型补0。整形晋升后,留神负数的源反补码雷同。int main(){ char b = 229; //存储时:229是负数,源反补码都雷同 //0000 0000 0000 0000 0000 0000 1110 0101 负数首位为0,其余位补0 //b内存中存储的是:1110 0101 //读取时,char类型打印为整型,整型晋升 //%d 示意有符号整形,首位为符号位,1110 0101首位为1,正数 //如果是打印 %u 打印无符号整形,所有位都为数值位,源反补码雷同。 //char类型为有符号类型,依据首位决定补什么 //补码:1111 1111 1111 1111 1111 1111 1110 0101 首位为1,全副补1 //反码:1111 1111 1111 1111 1111 1111 1110 0100 补码减一 //源码:1000 0000 0000 0000 0000 0000 0001 1011 取反//输入的值: -27 printf("%d",b); return 0;}大小端字节序存储以字节为单元进行存储。0x12345678 十六进制位 12是最高位字节的数据,78是最低位字节的数据大端存储: 低位 12 34 56 78 高位 把高位字节数据寄存在低位处小端存储: 低位 78 56 34 12 高位 把低位字节数据寄存在低位处浮点型在内存中的存储留神:浮点数在内存中可能不能准确保留,所以个别不必 == 号进行比拟,个别是用差值,看是否在肯定范畴内。存储浮点数时整数和浮点数在内存中的存储形式是有差别的。依据国内IEEE754的规范:任意二进制浮点数都能够示意成下列模式。浮点数的计数形式:(-1)^S*M*2^E(-1)^S示意符号位,S为0,则为负数;为1,则为正数M示意有效数字的,大于1,小于2 (用二进制示意的)2^E示意指数位。内存中存储的就是S、E、M三个数据(对应32位float类型)[bit0]1bit存储S,[bit1-bit8]8bit存储E,[bit9-bit31]23bit存储M。(对应64位double类型)[bit0]1bit存储S,[bit1-bit11]11bit存储E,[bit9-bit63]52bit存储M。留神:计算机外部保留M时,默认这个数的第一位总是1,所以能够省略,只保留小数点后的位数。 ...

June 19, 2022 · 1 min · jiezi

关于c:字符指针与数组指针

内存中地址调配办法内存中地址调配是以字节为单位的即:每一个字节都有惟一一个地址例如: int a = 0x12345678;//如果a的地址是 0xffff4444//如果是小端存储 低地址 44 44 ff ff 高地址//那么以char类型解援用 0xffff4445 地址的数据,失去的是0x44 。字符指针char* p1 = "abcde";char* p2 = "abcde"; 上述两个变量定义初始化,相当于创立一个字符串常量abcde,而后将这个常量别离赋值给不同的指针,所以两个指针指向同一个地址当定义两个雷同的常量字符串时,因为字符串abcde是常量字符串,不能被更改所以在内存中是不会被创立两份的,只创立一份,两个变量共用。所以,指针p1和指针p2都会指向同一个地址char arr1[] = "abcde";char arr2[] = "abcde";这里是用abcde去初始化两个不同的数组,所以arr1不等于arr2。数组指针int (*p)[10];//定义数组指针留神:* p这里必须打括号,因为[]的优先级高于星号 ,所以必须加上括号保障p先与星号联合。它指向一个大小为10个int型的数组。数组名和&数组int arr[10] = {0};printf("%p\n",arr);printf("%p\n",arr[0]);printf("%p\n",&arr);//三个输入后果雷同//然而arr代表的是数组首元素地址,代表一个int元素的大小,它是int*类型。//&arr代表的是数组的地址,代表整个数组的大小,它是数组指针类型int (*)[10]//它们代表的范畴不同int* a = arr;int (*p)[10] = &arr; p是一个指针,只占4个字节,指向一个数组(指向的是数组而不是数组的首元素)char* arr[5];p = &arr; //指针p的类型为:char* (*p)[5]//(*p)示意p是一个指针//[5]示意指向的是大小为5的数组//char* 示意指向的数组是char*型int* arr[10]; //arr[0] 是int*型,arr是int**型int* (*p)[10] = &arr;//p 是数组指针,指向的是arr整个数组,范畴是整个数组//*p解援用,解进去的是数组首元素的地址,相当于arr(int**类型)//*(*p) 解进去是数组首元素,相当于arr[0] (int*类型)数组指针在二重数组中的利用#define _CRT_SECURE_NO_WARNINGS 1#include <stdio.h>int print(int(*p)[5]){ for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { printf("%d ", *(*(p + i) + j)); } printf("\n"); } return 0;}int main(){ int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} }; print(arr); return 0;}

June 19, 2022 · 1 min · jiezi

关于c:C语言的算数转换

算数转换当执行算术运算时,如果操作对象的类型不同,就会产生数据类型转换。转换规则: 朝着精度更高、长度更长的方向转换保无符号规定:当运算符两边别离是signed 有符号类型和unsigned无符号类型时,产生算术转换,将signed有符号类型转换为无符号类型。例如:下列输出后果为 大于#include <stdio.h>int i ; //全局变量未初始化,默认为0int main(){ i--; //i为有符号类型,i = -1 if (i > sizeof(i)) { printf("大于"); } else { printf("小于"); }}在if语句判断时,产生了数据类型的转换 i为-1二进制为1000 0000 0000 0000 0000 0000 0000 0001补码为:1111 1111 1111 1111 1111 1111 1111 1111算数转换,当初零碎认定i为unsigned int型,无符号类型均为负数,源反补码雷同所以当初i的源码也为1111 1111 1111 1111 1111 1111 1111 1111所以在if语句判断这里,i是大于4的(sizeof(i) = 4)留神:i的理论值并没有产生扭转,只是在运算时,解析办法变了。

June 19, 2022 · 1 min · jiezi

关于c#:NET-PDF转WordDocDocx

PDF文件是一种用于贮存和传输内容的文件格式,其传输内容的形式与操作系统、应用程序以及硬件无关,因而可能在各个平台进行内容传递并放弃其显示成果。但PDF文件在编辑内容的时候不太不便,且反对编辑的利用大多免费。而Word文档是一种非常适合编辑及贮存内容的文件,Word文档的编辑软件功能丰富、使用方便,是比拟常见软件。如果咱们能够将PDF文件转为Word文档,内容编辑就会变得十分不便。本文将介绍通过简略的编程,将PDF文件转为Word文档,包含Doc和Docx。本文所应用的转换方法须要用到收费Office库Free Spire.PDF for .NET,首先须要引入dll文件。 1.应用Nuget可在Nuget治理中搜寻Free Spire.PDF装置,或在控制台输出以下代码装置:PM> Install-Package FreeSpire.PDF 2.手动增加在Free Spire.PDF for .NET官网下载解压,将dll增加到依赖项中。 将PDF文档转换为Word文档转换代码非常简单,仅需三个步骤: 创立 PdfDocument 类的对象。应用 PdfDocument.LoadFromFile() 办法从磁盘加载PDF文档。应用 PdfDocument.SaveToFile() 办法将PDF文档转换为Word文档并保留,可抉择Word文档格局。代码示例:C# using Spire.Pdf;namespace PDFToWord{ class Program { static void Main(string[] args) { //创立PdfDocument类的对象 PdfDocument pdf = new PdfDocument(); //加载PDF文档 pdf.LoadFromFile("Sample.pdf"); //将PDF文档转为Word文档并保留,可抉择格局 pdf.SaveToFile("result.docx", FileFormat.Docx); } }}VB.NET Imports Spire.PdfNamespace PDFToWord Class Program Private Shared Sub Main(args As String()) '创立PdfDocument类的对象 Dim pdf As New PdfDocument() '加载PDF文档 pdf.LoadFromFile("Sample.pdf") '将PDF文档转换为Word文档并保留,可抉择Word文档格局 pdf.SaveToFile("result.docx", FileFormat.Docx) End Sub End ClassEnd Namespace转换成果示例: ...

June 17, 2022 · 1 min · jiezi

关于c++:C-静态反射在网易云信-SDK-中的实践

对话零碎目前网易云信 IM SDK 反对全平台,IM SDK 每次发版除了要针对新性能进行测试外,回归测试也占了很大比重,随着 IM SDK 反对的平台越来越多,API 接口越来越丰盛,每次须要回归测试的范畴也在一直减少,如果以人工来实现,不仅效率低下,而且可能会产生漏测、误判等问题。为了进步回归效率、继续监控程序品质,云信在“品质保障体系”建设中投入了大量精力来搭建和欠缺“自动化测试平台”,“API 自动化测试”作为自动化测试平台的重要组件,为“单元测试”、“回归测试”、“每日构建”等性能提供了无力撑持,接入自动化测试平台十分有意义,其中“API 自动化测试”的次要流程如下图所示,本文就“依据 API 信息转为 API 调用”、“API 调用后果转换为用例执行后果数据”在桌面端(Windows、MacOSX、Linux)实现的关键技术进行探讨。 为什么要应用反射下图所展现的内容是由“自动化测试平台”下发的用例信息(为了不便展现,字段有裁剪)。 其中 className、methodName 形容了 SDK-API 的 NIMAuthService::login 办法,params 结点则形容了 login 办法的参数,依据上节提到的“依据 API 信息转为 API 调用”、“API 调用后果转换为用例执行后果数据”,其中波及到转换有两种: API 转换依据用例传入的 className、methodName 来找到对应的 API。 从上图的数据上来看要找到 NIMAuthService::login 进行调用。 数据转换JsonData2cppStruct,测试平台 Json 数据转换到 C++ 数据。 cppStruct2JsonData,C++ 执行后果数据转换为 Json 数据上报到测试平台。 从上图的数据上来看要把 data 节点的数据转换为 NIMAuthInfo,做为 NIMAuthService::login 的调用参数. 对于这种场景应用“反射”无疑是最合适与优雅的形式,为什么这么说呢,能够进行如下的比照: IM SDK-API(仅示例): namespace nim {struct AuthInfo {std::string accid;std::string token;std::string appkey;}; struct AuthCallbackParam {std::string accid;bool result;int step;};using LoginCallback = std::function<void(const AuthCallbackParam&)>;struct NIMAuthService {static bool login(const AuthInfo& info) {std::cout << info.accid << " / " << info.token << " / " << info.appkey << std::endl;return true;}static void loginEx(const AuthInfo& info,const LoginCallback& callback) {std::cout << info.accid << " / " << info.token << " / " << info.appkey << std::endl;if (callback != nullptr) {callback(true);}}};}不应用反射机制,须要依据输出的 Json 数据来查找对应的 service,并找到对应的办法,把 Json 数据转换为对应的 C++ 构造,而后进行 API 调用,基中会波及到大量的反复逻辑的判断。 ...

June 16, 2022 · 8 min · jiezi