如何在C语言中生成含数字、大小写字母的无重复字符随机密码?
无重复随机C语言密码实现要点
- 原代码的核心缺陷:完全没有已选字符的校验逻辑,仅按随机类型从对应字符集里取字符,必然会出现大量重复字符;其中在循环外部初始化
selector的操作属于冗余逻辑,因为每轮选中字符后都会重新给selector赋值,对选字符的过程没有实际作用。 - 前置边界判断:所有可用无重复字符总共有10个数字+26个小写字母+26个大写字母=62个,如果设定的
LENGTH超过62,本身就不可能实现全字符无重复,需要先做长度校验。
可落地的实现方案
方案1:最小改动适配现有代码结构
- 新增和总字符池等长的状态标记数组,逐位记录每个字符是否已经被选入密码
- 每次随机选中候选字符后,先查状态标记:如果已经被使用过,就重新随机抽取,直到抽到未使用的字符,再把它写入密码位、更新标记状态
- 该方案的明显缺陷:当密码长度接近62时,剩余可用字符极少,会触发大量无效重抽,运行效率很低
方案2:洗牌法(无重抽、无重复)
把所有可用字符拼成一个完整的字符池,用Fisher-Yates算法将字符池完全打乱,直接从打乱后的池子里按顺序取前LENGTH个字符作为密码即可。这种方式不需要额外的重复判断,时间复杂度低,也不会出现任何重复字符。
对应的参考实现代码:
#define AVAILABLE_TOTAL 62 // 10个数字 + 26个小写字母 + 26个大写字母 void createPassword() { // 边界校验 if (LENGTH > AVAILABLE_TOTAL) { printf("错误:密码长度超过无重复字符上限,无法生成\n"); return; } char password[LENGTH + 1]; // 构建全量可用字符池 char charPool[AVAILABLE_TOTAL + 1]; strcpy(charPool, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); // Fisher-Yates 洗牌打乱字符顺序 for (int i = AVAILABLE_TOTAL - 1; i > 0; i--) { int swapPos = rand() % (i + 1); char temp = charPool[i]; charPool[i] = charPool[swapPos]; charPool[swapPos] = temp; } // 取前LENGTH个字符组成无重复密码 strncpy(password, charPool, LENGTH); password[LENGTH] = '\0'; // 补字符串结束符 printf("Vytvorene heslo: %s\n", password); }
内容的提问来源于stack exchange,提问作者vacexpfleger
相关产品推荐
相关产品推荐

