C++分配1-9不重复随机数失败,求助排查代码逻辑问题
问题描述
我尝试为变量A、B、C…I分配1至9的不重复数字,计划通过计数器方法实现:每次变量与其他变量不同则获得1个点数,累计8个点数时将该数字分配给变量。我编写了包含主文件、函数文件、头文件的三段代码(如下),最初使用<cstdlib>库时出现0、-1934、42130等异常数值,切换到<random>库后则完全没有输出。尝试取消使用std命名空间也未解决问题,怀疑代码逻辑存在缺陷,请问问题出在哪里?
主文件
#include <iostream> #include <random> #include "test.hpp" using namespace std; int main() { srand((unsigned)time(0)); int A = 0, B = 0, C = 0, D = 0, E = 0, F = 0, G = 0, H = 0, I = 0, sum = 0; no (A); while (C == A or C == 0) { no (C);} while (B == A or B == 0 or B == C) { no (B);} while (D == A or D == 0 or D == C or D == B) { no (D);} while (E == A or E == 0 or E == C or E == B or E == D) { no (E);} while (F == A or F == 0 or F == C or F == B or F == D or F == E) { no (F);} while (I == A or I == 0 or I == C or I == B or I == D or I == E or I == F) { no (I);} while (G == A or G == 0 or G == C or G == B or G == D or G == E or G == F or G == I) { no (G);} while (H == A or H == 0 or H == C or H == B or H == D or H == E or H == F or H == I or H == G) { no (H);} cout << A << " is A \n"; cout << B << " is B \n"; cout << C << " is C \n"; cout << D << " is D \n"; cout << E << " is E \n"; cout << F << " is F \n"; cout << G << " is G \n"; cout << H << " is H \n"; cout << I << " is I \n"; }
函数文件
#include <iostream> #include <random> #include "test.hpp" void no(int & x) { x = (rand() % 9) + 1; }
头文件(test.hpp)
void no(int & x);
问题分析与解决
1. 随机数库依赖错误
你代码里用的rand()属于<cstdlib>库,和<random>库无关。切换到<random>后仍调用rand(),会触发未定义行为——要么编译失败,要么运行时无法生成有效随机数,导致循环一直无法退出,自然看不到输出。
另外,最初用<cstdlib>时出现异常数值,是因为没包含<ctime>库(srand((unsigned)time(0))需要这个库),导致time函数未定义,随机数种子无效,rand()生成的数值异常。
2. 循环逻辑冗余且存在顺序隐患
你逐个变量写循环判断重复,不仅代码冗余,还存在逻辑顺序问题:比如先处理C再处理B,B的判断条件包含C的值,虽然逻辑上能运行,但一旦某个变量的循环条件出现漏洞,就会陷入死循环。
3. 完全未实现计数器逻辑
你提到的“变量与其他变量不同得1分,累计8分分配数字”的逻辑,在代码里完全没有体现,实际用的是简单的重复判断循环,和最初设计偏离。
修复方案
方案一:修正随机数使用并简化赋值逻辑
如果继续用rand(),必须补全依赖库,同时用数组+已使用列表简化赋值:
#include <iostream> #include <cstdlib> #include <ctime> #include <vector> #include <algorithm> using namespace std; int main() { srand((unsigned)time(0)); int vars[9] = {0}; vector<int> used; for(int i=0; i<9; i++){ int num; do{ num = rand()%9 +1; }while(find(used.begin(), used.end(), num) != used.end()); vars[i] = num; used.push_back(num); } cout << vars[0] << " is A\n"; cout << vars[1] << " is B\n"; cout << vars[2] << " is C\n"; cout << vars[3] << " is D\n"; cout << vars[4] << " is E\n"; cout << vars[5] << " is F\n"; cout << vars[6] << " is G\n"; cout << vars[7] << " is H\n"; cout << vars[8] << " is I\n"; return 0; }
方案二:实现你最初的计数器逻辑
如果一定要用计数器方式,可通过比较已分配变量的数量来判断:
#include <iostream> #include <cstdlib> #include <ctime> using namespace std; int assignNum(int used[], int count){ int num; while(true){ num = rand()%9 +1; int match = 0; for(int i=0; i<count; i++){ if(num != used[i]) match++; } // 已分配count个变量,和所有变量都不同则match等于count if(match == count){ break; } } return num; } int main() { srand((unsigned)time(0)); int used[9]; used[0] = assignNum(used, 0); // A used[1] = assignNum(used, 1); // B used[2] = assignNum(used, 2); // C used[3] = assignNum(used, 3); // D used[4] = assignNum(used, 4); // E used[5] = assignNum(used, 5); // F used[6] = assignNum(used, 6); // G used[7] = assignNum(used, 7); // H used[8] = assignNum(used, 8); // I cout << used[0] << " is A\n"; cout << used[1] << " is B\n"; cout << used[2] << " is C\n"; cout << used[3] << " is D\n"; cout << used[4] << " is E\n"; cout << used[5] << " is F\n"; cout << used[6] << " is G\n"; cout << used[7] << " is H\n"; cout << used[8] << " is I\n"; return 0; }
内容的提问来源于stack exchange,提问作者Devil's Advocate 2321
相关产品推荐
相关产品推荐

