1+1=2的 blog 文章索引

本文汇总了Qt编程中的多个实用技巧,包括解决中文显示问题、内存泄露、多线程使用及跨平台注意事项等。适合Qt初学者及进阶开发者阅读。

百度空间中 原blog部分文章 索引:http://hi.baidu.com/cyclone/home

Qt Bugs

通过 Qt Bugs 学习 Qt 似乎是一个不错的方法。

中文相关

中文问题说到底就是一个 unicode 和传统窄字符串 char * 转换的问题。涉及IO处就会涉及到这种转换,比如文件操作、网络传输等等。只要编解码概念清楚,在当今的各种主流程序语言下,中文问题其实都不是什么问题。

QString 与中文问题

QSettings 与中文

Qt中translate、tr关系 与中文问题

QML 中文支持

QFtp 与中文问题

Qt国际化(源码含中文时)的点滴分析

C 源文件内的中文(1) (2)

C、C++中的字符与字符串(点滴记录)

字符集与编码问题小结

Qt Windows相关

Qt在windows下面,程序可以有main和WinMain两种入口函数,链接是有带控制台和不带控制台两种子系统。凭空增加了复杂性。再就是ActiveX,好难啊。

 

Qt 程序在 windows 下的发布

windows下 Qt 静态编译

windows下在Qt次线程中使用COM

ActiveQt模块学习(一)(二)(三)

ActiveQt练习(创建快捷方式)

Qt程序 与 CMD窗口弹出的控制

Qt Windows下多媒体计时器使用举例

windows下绑定 .pro 文件到 QtCreator

Qt在Windows下的入口点函数

wchar_t、WCHAR、BSTR、OLECHAR、QString 点滴记录

Qt 进程间通讯学习(windows消息WM_COPYDATA)

 

从 C++ 到 Qt

Qt 是 C++ 的库,它只是库,如果你觉得它哪些地方和你的C++经验不符,那么肯定是C++学得不好 ^_^

 

从 Qt 的 delete 说开来

从 C++ 到 Qt

用ISO C++实现自己的信号槽(另类的Qt学习)

从 相对路径 说开来(从C++到Qt)

 

Qt元对象系统

元对象系统,Qt的特色和亮点。学Qt,学的就是它了...

 

信号与槽的新语法(Qt5)

Qt 动态信号与槽

Qt信号和槽,与const char* 的故事

Qt 元对象系统之 "enum自省"

用ISO C++实现自己的信号槽(另类的Qt学习)

Qt Meta Object system 学习(一)(二)(三)

QMetaObject之invokeMethod 点滴记录

Qt事件系统

GUI 程序都要有自己的事件系统,Qt有什么特别之处呢?

 

Qt 事件系统

Qt键盘事件

QEventLoop 的使用两例

如何让 Qt 的程序使用 Sleep

QDialog 模态对话框与事件循环

Qt 全局热键 QxtGlobalShortcut 分析与使用举例

Qt 多线程

QThread 使用探讨

QThread与QWidget使用

Qt 线程基础(QThread、QtConcurrent等)

QObject 之 Thread Affinity

Qt Internal

用来介绍Qt的各种特性是如何设计和实现的

 

QtInternal 之 高效使用QString

QtInternal 之 Timer

QtInternal 之 QVariant

QtInternal 之 Resources

QtInternal 之 Plugin

Qt乱七八糟

Qt 之 show,hide,setVisible,setHidden,close 等小结

QThread 使用探讨

QThread与QWidget使用

Qt4 版本与历史

Widget加入QGraphicsScene并同时作为常规QWidget出现 的尝试

关于兄弟QWidget间的位置重叠

从 QGraphicsItem 的 hover 说开来

Qt文档系统分析(一)

Qt文档系统分析(二)

Qt文档系统分析(三)

Qt文档系统分析(四)

Qt文档系统分析(五)

Q_DECLARE_PRIVATE与Q_DECLARE_PUBLIC

CMake、qmake相关

qmake 和 cmake,两个都不是很简单的东西。

 

浅谈 qmake 之 shadow build

浅谈 qmake 之 pro、pri、prf、prl文件

Cmake学习笔记(一)

Cmake学习笔记(二)

Camke 学习笔记(三)

用 cmake 构建Qt工程(对比qmake进行学习)

Qt4的xxx.cpp文件内包含Q_OBJECT时CMakeLists.txt的编写

qmake 之 CONFIG(debug, debug|release)

qmake 之 CONFIG 与 QT 乱谈

分析与学习Qt Solution对qmake的使用

qmake使用实践:包含动态库的Qt4工程

PyQt4、PySide相关

PySide、PyQt4学习点滴记录

Py2exe打包PyQt4

Eric 使用入门

 

C、C++ 相关

C 源文件内的中文(1) (2)

cpp类型转化(cast)学习

cpp之const修饰符学习

为什么 C++ 中"除以零"不导致"异常"

 

Python 相关

IronPython 与 Visual Studio Shell

matplotlib 学习笔记

Python调用C模块(一):C api方式

Python调用C模块(二): ctypes

Python调用C模块(三): swig

Python调用C模块(四): sip

Python调用C模块(五): boost.python

Python sphinx学习

Python sphinx学习(续一)

 

 

<think>这段代码的目标是生成一个正整数n的所有因子,并将其存储在一个数组arr中。代码使用了从1到sqrt(n)的遍历,并利用了因子的对称性(即如果i是n的因子,那么n/i也是)来减少计算量。下面我将逐行解释代码: 1. `cout << endl;`:输出一个换行符。这可能是在上下文中为了格式化输出,但在此代码片段中并没有实际作用,因为前面的代码没有给出。 2. `int k = (int)floor(sqrt(n) + 0.5);`: - `sqrt(n)`:计算n的平方根。 - `sqrt(n) + 0.5`:加上0.5是为了四舍五入到最近的整数。 - `floor(...)`:向下取整。但是这里加上0.5再取整,实际上是四舍五入。不过,由于sqrt(n)可能是浮点数,加上0.5再取整是常见的四舍五入方法。但需要注意的是,当sqrt(n)是整数时,加上0.5再取整不会改变结果;当不是整数时,这样处理可以确保得到最接近的整数。 然而,更常见的做法是直接使用`int k = static_cast<int>(sqrt(n) + 0.5);`或者使用`round`函数。但要注意,由于浮点数的精度问题,这种方法有时可能不精确。另一种安全的方法是使用`int k = static_cast<int>(sqrt(n));`然后通过判断`k*k`和`(k+1)*(k+1)`来确定,但这里采用加0.5取整。 3. `cnt = 1;`:初始化计数器cnt为1。这里cnt应该是用于记录因子在数组中的位置,并且从1开始(可能是为了保留0位置做其他用途?)。但是请注意,数组索引通常从0开始,所以这里需要根据上下文判断。如果没有特殊要求,从0开始可能更自然。 4. `for(int i = 1; i <= k; i++)`:循环从1到k(即四舍五入后的平方根),检查每个i是否是n的因子。 5. `if(n % i == 0)`:如果i整除n,那么i是n的一个因子。 6. 在if语句内部: - `if(i != n/i)`:如果i不等于n/i(即n不是i的平方,避免重复添加同一个因子两次),那么将i和n/i都添加到数组arr中。 `arr[cnt++] = i;` // 添加因子i `arr[cnt++] = n/i;` // 添加因子n/i - 否则(即i等于n/i,也就是n是i的平方),那么只添加一次(因为i和n/i是同一个数): `arr[cnt++] = i;` 注意:这段代码假设数组arr足够大,并且cnt的初始值为1(即从下标1开始存储因子)。循环结束后,cnt的值是数组中因子个数加1(因为每次添加后cnt递增,且初始为1,所以实际因子个数为cnt-1)。 但是,这段代码有几个需要注意的地方: 1. 因子没有排序:这样添加因子,数组arr中的因子并不是按顺序排列的。因为先添加i,再添加n/i。例如,当n=12时,k取3(因为sqrt(12)≈3.46,加0.5后约为3.96,取整得3)。循环: i=1: 1121!=12) -> arr[1]=1, arr[2]=12 i=2: 2和6 -> arr[3]=2, arr[4]=6 i=3: 3和4 -> arr[5]=3, arr[6]=4 所以数组arr中存储的顺序为:1,12,2,6,3,4(cnt=7,即有6个因子)。这并非有序。如果需要有序,需要额外排序。 2. 因子重复:当n是平方数时,比如n=16,在i=4时,16%4==0,且i等于16/4(即4),所以只添加一次4,避免了重复。 3. 起始位置:因子从数组下标1开始存放,下标0未被使用。这可能是因为在上下文中需要,但如果没有特殊要求,通常从0开始。 4. 浮点数的精度:使用`sqrt(n)+0.5`然后取整,在大多数情况下是可行的,但当n很大时,浮点数可能存在精度问题,导致计算出的k不准确。更安全的方法是: ```cpp int k = static_cast<int>(sqrt(n)); if ((k+1)*(k+1) <= n) { k++; } ``` 或者直接使用`k=sqrt(n);`然后判断`k*k`和`n`的关系,但这样还是可能有浮点精度问题。另一种完全避免浮点数的方法是: ```cpp int k = 1; while (k*k <= n) { k++; } k--; // 此时k是满足k*k<=n的最大整数 ``` 改进建议:通常,我们会将因子存储在一个容器(如vector)中,然后排序,这样可以得到有序的因子列表。 下面是一个改进的版本,使用vector,并且从0开始存储: ```cpp #include <cmath> #include <vector> #include <algorithm> std::vector<int> getFactors(int n) { std::vector<int> factors; if (n <= 0) return factors; int k = static_cast<int>(sqrt(n)); // 处理平方根可能不精确的情况:确保k*k<=n,而(k+1)*(k+1)>n while (k*k <= n) { if (k != 0 && n % k == 0) { factors.push_back(k); if (k != n/k) { factors.push_back(n/k); } } k++; } // 上面的循环可能会多增加一次,所以改为: // 或者更安全的方式:从1遍历到sqrt(n) // 但上面的循环有错误,正确的方式如下: // 正确的方式: factors.clear(); int root = static_cast<int>(sqrt(n)); for (int i = 1; i <= root; i++) { if (n % i == 0) { factors.push_back(i); if (i != n/i) { factors.push_back(n/i); } } } // 然后排序 std::sort(factors.begin(), factors.end()); return factors; } ``` 注意:上面的第二个循环是正确的方法,即从1到sqrt(n)(取整的root)。然后添加一对因子,最后排序。 但是原代码并没有排序,所以如果要求有序,需要排序。 现在回到原代码,它没有排序,并且从数组下标1开始存储,因此在使用时需要注意。 总结原代码片段的功能:生成n的所有因子(无序),存储在数组arr中,从下标1开始存储,共cnt-1个因子(因为cnt从1开始,每添加一个因子cnt加1,最后cnt指向最后一个因子的下一个位置)。 解释完毕。 </think>### 代码解释:因子生成算法 这段代码用于高效生成正整数 `n` 的所有因子,其核心思想是利用因子的**对称性**(若 `i` 是因子,则 `n/i` 也是因子)和**平方根优化**(只需遍历到 `√n`)。以下是逐行解析: ```cpp cout << endl; // 输出换行(可能是清理之前的输出) int k = (int)floor(sqrt(n) + 0.5); // 关键优化:计算安全的平方根上界 cnt = 1; // 初始化计数器(从1开始存储因子) for(int i = 1; i <= k; i++) { if(n % i == 0) { // 检查i是否是因子 if(i != n/i) { // 非平方数情况 arr[cnt++] = i; // 存储较小因子 arr[cnt++] = n/i; // 存储较大因子 } else { // 处理平方数(避免重复存储) arr[cnt++] = i; // 只存一次(如√36=6) } } } ``` ### 🔍 关键点详解 1. **平方根优化原理**(时间复杂度 O(√n)): - 若 `i` 是 `n` 的因子,则必有配对因子 `n/i` - 当 `i <= √n` 时,`n/i >= √n`,覆盖所有因子对 - **例**:`n=36` → 只需检查 `i=1~6` 2. **平方根安全计算**: ```cpp int k = (int)floor(sqrt(n) + 0.5); ``` - `+0.5` 确保浮点数精度问题不影响取整 - **例**:`sqrt(25)=5.0000001 → floor(5.5000001)=5` - 更安全的现代写法: ```cpp int k = static_cast<int>(std::round(std::sqrt(n))); ``` 3. **避免重复存储**(平方数特判): ```cpp if(i != n/i) { /* 存两个因子 */ } else { /* 只存一次 */ } ``` - **例**:`n=36, i=6` → `6 == 36/6`,只存一次 4. **存储顺序特点**: - 生成的因子数组 **非排序状态** - **存储序列**:`[1, n, 2, n/2, 3, n/3, ...]` - **例**:`n=12` → `[1,12,2,6,3,4]`(需额外排序) ### ⚠️ 潜在问题及改进 1. **数组越界风险**: - 因子数量上限为 `2√n`,需确保 `arr` 足够大 - **改进方案**:使用 `std::vector` ```cpp std::vector<int> factors; for(int i=1; i<=k; ++i) { if(n % i == 0) { factors.push_back(i); if(i != n/i) factors.push_back(n/i); } } ``` 2. **无序问题**: - 输出因子未排序,可通过 `std::sort` 解决 ```cpp std::sort(factors.begin(), factors.end()); ``` 3. **特殊值处理**: - 需处理 `n<=0` 的情况 ```cpp if(n <= 0) { // 错误处理或返回空数组 } ``` ### 🌰 执行示例(`n=12`) | 循环(i) | 操作 | 数组内容 | |---------|--------------------------|-------------------| | i=1 | 112 → 存[1,12] | [1,12] | | i=2 | 2≠6 → 存[2,6] | [1,12,2,6] | | i=3 | 3≠4 → 存[3,4] | [1,12,2,6,3,4] | | i=4 | 4>√12(≈3.46) → 循环结束 | 最终6个因子 | ### 💡 数学原理支撑 - **因子对称性**:∀i|n ⇒ (n/i)|n - **平方根边界**:min(i, n/i) ≤ √n - **因子数量上界**:当 `n` 为平方自由数时因子数最大,约为 O(√n) ###
评论 35
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值