C++类方法for循环内成员变量无法更新,仿Python生成器异常
解决C++生成器类返回重复除数的问题
嘿,我一眼就看到你代码里的问题了——每次调用next()都返回2,循环停不下来,核心原因是**for循环的i++在找到除数后没机会执行**!
问题根源分析
你看next()方法里的这段代码:
for(; i*i<=x;i++) { if(x%i == 0) { divs.emplace_back(i); if(!((i+1)*(i+1)<x+1)) end = true; return i; } }
当i=2满足10%2==0时,你直接return i跳出了函数,这时候for循环末尾的i++根本没被执行!所以i永远停在2,每次调用next()都会重复检查i=2,自然每次都返回2,循环也就无限运行了。
另外,你判断end的条件!((i+1)*(i+1)<x+1)写得太绕,而且逻辑不准确,应该直接判断i*i > x来确定是否没有更多除数了。
修正后的代码
我给你调整了next()方法的逻辑,确保i每次都会递增,同时修正了end的判断逻辑,还补充了对1和数字本身的处理(如果你不需要可以去掉):
using ull = unsigned long long int; #include <vector> #include <iostream> using namespace std; class Divisors { public: ull x; vector<ull> divs; ull i; bool end; Divisors(const ull &x) : x(x), i(1), end(false) { } ull next() { // 先处理除数1 if (i == 1) { i++; divs.emplace_back(1); return 1; } // 寻找小于等于sqrt(x)的除数 for (; i*i <= x; ) { if (x % i == 0) { ull result = i; i++; // 在返回前先递增i,避免下次重复检查 divs.emplace_back(result); // 当i的平方超过x时,说明没有更多小除数了 if (i*i > x) end = true; return result; } i++; // 当前i不是除数,手动递增 } // 处理大于sqrt(x)的除数(比如10的5)或者数字本身 if (!end) { end = true; // 避免重复添加(比如x是平方数的情况,比如4的2) if (x != divs.back()) { divs.emplace_back(x); return x; } } return 0; } }; int main() { Divisors divs(10); int cnt = 0; while (!divs.end && cnt < 100) { auto div = divs.next(); cout << div << endl; cnt++; } return 0; }
修正点说明
- 确保i递增:把
for循环的i++移到循环体内部,不管找到除数还是没找到,i都会递增,不会因为return跳过。 - 修正end判断:直接用
i*i > x来判断是否没有更多小除数,逻辑更清晰准确。 - 补充1和自身的处理:原代码没处理1和数字本身,现在加上后,输入10会依次输出
1、2、5、10,符合除数的完整集合。 - 避免重复添加:当x是平方数时(比如4),不会重复添加平方根(比如2)。
现在运行这段代码,就不会再无限输出2了,会正确遍历所有除数后停止循环。
内容的提问来源于stack exchange,提问作者Rahat Zaman
相关产品推荐
相关产品推荐

