生成密码c

news2024/12/27 13:45:08

需求

目前需要实现生成8-12位密码,密码要求至少包含一位数字,一位大写字母,一位小写字母,一位特殊字符。特殊字符仅包含(“@”,“!”,“_”)

需求分析

可知我们需要1个功能,1.生成默认随机密码 ,

源码

#include <stdio.h>
#include <stdlib.h>
// rand(),srand()
#include <string.h>
#include <time.h>

#define MIN_PASSWORD_LENGTH 8
#define MAX_PASSWORD_LENGTH 12
void shuffle (char *password)
{
    int i,j;
    int length = strlen(password);
    for (i = 0; i < length; i++)
    {
        j = rand() % length;
        char temp = password[i];
        password[i] = password[j];
        password[j] = temp;
    }
}

void generatePassword(char *password, int length)
{

    const char *numbers = "0123456789";
    const char *upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    const char *lowerChars = "abcdefghijklmnopqrstuvwxyz";
    const char *specials = "@!_";
    int allLength = strlen(numbers) + strlen(upperChars) + strlen(lowerChars) + strlen(specials) + 1;
    char charall[allLength];
    strcpy(charall,numbers);
    strcat(charall,upperChars);
    strcat(charall,lowerChars);
    strcat(charall,specials);
    int i, charPos;
    
    // 初始化密码数组
    for (i = 0; i < length; i++)
    {

        password[i] = 0;
    }

    // 确保密码至少包含一个数字、一个大写字母、一个小写字母和一个特殊字符
    password[0] = numbers[rand() % strlen(numbers)];
    password[1] = upperChars[rand() % strlen(upperChars)];
    password[2] = lowerChars[rand() % strlen(lowerChars)];
    password[3] = specials[rand() % strlen(specials)];
   
    for (i = 4; i < length; i++)
    {
        charPos = rand() % (strlen(charall));
        password[i] = charall[charPos];
    }
    //  打乱密码中的字符顺序,以确保随机性
    shuffle(password);
    password[length] = '\0';
}
int generateLength(int min,int max)
{
    return rand() % (max - min + 1) + min;
}
int main()
{
    int i;
    char password[MAX_PASSWORD_LENGTH+1];
    srand(time(NULL)); 
    for (i = 1; i <= 50; i++)
    {
        int length = generateLength(MIN_PASSWORD_LENGTH,MAX_PASSWORD_LENGTH);
        
        generatePassword(password, length);
        
        printf("Number : %d , the length of pwd : %d, Generated Password: %s\n", i, length, password);
    }

    return 0;
}

运行结果

在这里插入图片描述
在这里插入图片描述

代码分析

初始化随机数生成器

函数原型

void srand(unsigned int seed);
srand(time(NULL));

这一行是用来初始化随机数生成器的。srand 函数是 C 标准库"stdlib.h"中的一个函数,它设置了随机数生成器的种子值。种子值通常是当前时间,由 time 函数返回,这样每次运行程序时生成的随机数序列都会不同。
这个种子值随后被 rand() 函数用来生成随机数序列。种子值是随机数生成算法的起点,不同的种子值通常会导致生成不同的随机数序列。

随机数序列生成器

rand() 函数是 C 语言标准库中的一个函数,用于生成伪随机数。这个函数返回一个介于 0 和 RAND_MAX 之间的整数,其中 RAND_MAX 是一个定义在 <stdlib.h> 头文件中的常量,这个值可能因编译器和平台而异。
在这里插入图片描述

字符串处理

声明一个char型数组来存储最终生成的随机密码,这里有个疑问是这个数组的长度为什么是MAX_PASSWORD_LENGTH + 1,如果仅仅为了存储密码的话,最多MAX_PASSWORD_LENGTH长度不就够了吗?

char password[MAX_PASSWORD_LENGTH + 1];

解惑

在 C 语言中,当你定义一个字符数组如 char password[MAX_PASSWORD_LENGTH + 1]; 时,这里的 +1 是为了确保数组有一个额外的空间来存储字符串的结束标志 ‘\0’,也就是空字符(null terminator)。这个空字符用于表示字符串的结束,在 C 语言中是处理字符串时的一个标准做法。

为什么需要额外的一位
考虑以下两个主要原因:

字符串结束标志

在 C 语言中,字符串以空字符 ‘\0’ 结尾。这个字符告诉函数(如 printf),字符串在哪里结束。如果不包含这个结束字符,字符串处理函数可能继续读取内存直到遇到一个随机的零字节,这可能导致未定义的行为,包括安全漏洞。

数组越界保护

在数组的末尾留出一个额外的空间可以作为缓冲,防止在字符串操作中意外写入数组界限之外,这也是一种常见的安全措施。

填充字符

不重复

for (i = 4; i < length; i++) {
        do {
            charPos = rand() % (strlen(numbers) + strlen(upperChars) + strlen(lowerChars) + strlen(specials));
            if (charPos < strlen(numbers)) {
                password[i] = numbers[charPos];
            } else if (charPos < strlen(numbers) + strlen(upperChars)) {
                password[i] = upperChars[charPos - strlen(numbers)];
            } else if (charPos < strlen(numbers) + strlen(upperChars) + strlen(lowerChars)) {
                password[i] = lowerChars[charPos - strlen(numbers) - strlen(upperChars)];
            } else {
                password[i] = specials[charPos - strlen(numbers) - strlen(upperChars) - strlen(lowerChars)];
            }
        } while (used[(unsigned char)password[i]]); // 确保不重复
        used[(unsigned char)password[i]] = 1;
    }

可重复

for (i = 4; i < length; i++)
    {

        charPos = rand() % (strlen(numbers) + strlen(upperChars) + strlen(lowerChars) + strlen(specials));
        if (charPos < strlen(numbers))
        {
            password[i] = numbers[charPos];
        }
        else if (charPos < strlen(numbers) + strlen(upperChars))
        {
            password[i] = upperChars[charPos - strlen(numbers)];
        }
        else if (charPos < strlen(numbers) + strlen(upperChars) + strlen(lowerChars))
        {
            password[i] = lowerChars[charPos - strlen(numbers) - strlen(upperChars)];
        }
        else
        {
            password[i] = specials[charPos - strlen(numbers) - strlen(upperChars) - strlen(lowerChars)];
        }
    }

为什么使用unsigned char而不是unsigned int

 while (used[(unsigned char)password[i]]); // 确保不重复
        used[(unsigned char)password[i]] = 1;

在 C 语言中,使用 (unsigned char)password[i] 而不是 unsigned int 对字符进行类型转换,主要是为了确保索引值落在数组的有效范围内,并且提高代码的可移植性和安全性。这里有几个原因为什么使用 unsigned char 比 unsigned int 更合适:

数组索引的安全性

在 C 语言中,数组索引应该是无符号字符或整数类型。使用 unsigned char 可以确保即使字符的 ASCII 值非常大(接近 UCHAR_MAX,即 unsigned char 类型的最大值),转换后的值仍然可以作为数组索引使用,而不会引起索引越界。

防止数据类型溢出

如果使用 unsigned int,而字符的实际值超过了 unsigned int 能表示的范围,那么会发生数据类型溢出,这可能导致不可预测的行为。使用 unsigned char 可以避免这种情况,因为它的范围较小,足以表示任何可能的字符值。

节省内存

unsigned char 通常只占用一个字节,而 unsigned int 可能占用四个字节(取决于平台)。在处理大量数据时,使用 unsigned char 可以节省内存空间。

可移植性

不同的编译器和平台可能对数据类型的大小有不同的定义。使用 unsigned char 可以提高代码的可移植性,因为它的大小是一致的(总是一个字节),而 unsigned int 的大小可能会有所不同。

语义明确

使用 unsigned char 作为数组索引明确表达了程序员的意图,即这个值是用来索引数组的,而不是用作其他计算。

无符号字符(unsigned char)为什么可以作为数组索引

大小和表示范围

unsigned char 类型通常占用一个字节(8位),其值域是从 0 到 255。这意味着它有足够的空间来表示数组索引,即使是在大多数情况下,数组的索引也不会超过这个范围。

类型安全性

在 C 语言中,数组索引在底层实际上是以整数形式处理的。当你使用一个变量作为数组索引时,编译器会将其转换为整数类型。unsigned char 作为一个无符号整数类型,可以安全地转换为一个更大的整数类型(如 int),而不会引起负值或符号扩展的问题。

性能

使用 unsigned char 作为索引可以提供更好的性能,因为它的大小较小,处理起来更快。在某些情况下,使用较小的数据类型可以减少内存使用和提高缓存效率。

避免负值

由于 unsigned char 是无符号的,它不会表示负值。这可以避免在某些情况下意外地将负值用作数组索引,这可能会导致未定义行为或程序崩溃。

符合标准

C 语言标准允许使用任何整数类型的值作为数组索引,包括 unsigned char。这意味着使用 unsigned char 作为数组索引是符合标准的,并且可以在所有遵循标准的 C 语言编译器上工作。

实际应用

在实际编程中,使用 unsigned char 作为数组索引可以帮助确保索引值的合法性和安全性,特别是在处理字符数据和字符串时。例如,当你遍历一个字符串并使用字符数组来跟踪字符出现的情况时,使用 unsigned char 可以确保索引值始终有效。

strlen()

size_t strlen(const char *str);

char *和char[]有什么区别

char *upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char upperChars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

存储方式:

char *upperChars = “ABCDEFGHIJKLMNOPQRSTUVWXYZ”;:这里 upperChars 是一个指向字符的指针,它指向一个静态分配的字符串字面量。字符串字面量是由编译器在程序的只读数据段中自动分配的,因此不能被修改。
char upperChars[] = “ABCDEFGHIJKLMNOPQRSTUVWXYZ”;:这里 upperChars 是一个字符数组,它在初始化时会将字符串字面量的内容复制到数组中。这意味着数组的内容存储在程序的可写内存区域,可以被修改。

内存分配:

指针声明不涉及数组的大小分配,它只是指向一个已经存在的字符串。
数组声明会根据初始化时提供的字符串长度(包括结尾的空字符 \0)在栈上分配内存。

修改内容:

通过指针 upperChars 指向的字符串是不可修改的,尝试修改它的任何字符都会导致未定义行为,通常是程序崩溃。
数组 upperChars 的内容是可以修改的,你可以更改数组中的任何字符。

数组大小:

对于指针,你不能得到它所指向的字符串的长度,除非你使用 strlen 函数。
对于数组,编译器知道数组的大小,因此你可以使用 sizeof(upperChars) 来得到字符串的长度,包括结尾的空字符。

用途:

指针通常用于指向字符串常量或动态分配的字符串。
数组通常用于创建可修改的字符串副本或在栈上存储固定长度的字符串。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2103212.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SVD的diffusers版本代码解析

https://zhuanlan.zhihu.com/p/701223363https://zhuanlan.zhihu.com/p/701223363ComfyUI中SVD 1.1:文生图,图生图,LCM应用 - 腾讯云开发者社区-腾讯云

[工具使用]git

git fetch 获取远程仓库内容&#xff0c;但未合入本地仓库&#xff1b; git rebase 获取远程仓库内容&#xff0c;并更改基地合入本地仓库&#xff1b; 将master分支的内容合入feature分支&#xff1a; 当在feature分支上执行git rebase master时&#xff0c;git会从master…

如何在不重装的前提下,将1TB的硬盘克隆到500GB的固态硬盘?

借助傲梅分区助手&#xff0c;你能够在Windows 11、10、8、7中轻松的将1TB硬盘克隆到500GB固态硬盘。并且无需重新安装系统&#xff0c;即可轻松实现1TB机械硬盘升级至固态硬盘。 问&#xff1a;可以克隆到较小的固态硬盘吗&#xff1f; “大家下午好&#xff01;我刚买了一块…

《数字信号处理》学习03-矩形序列,实指数序列和复指数序列

目录 一&#xff0c;矩形序列 1&#xff0c;由单位阶跃序列组成 2&#xff0c;由单位冲击序列组成 二&#xff0c;实指数序列 三&#xff0c;复指数序列 这篇文章着重学习&#xff1a;矩形序列&#xff0c;实指数序列和复指数序列。其它序列都比较简单&#xff0c;这里不再…

计算机毕业设计PySpark深度学习动漫推荐系统 动漫视频推荐系统 机器学习 协同过滤推荐算法 bilibili动漫爬虫 数据可视化 数据分析 大数据毕业设计

本推荐系统采用的是分层模型设计思想&#xff0c;第一层为前端页面模型设计&#xff0c;注重为实现页面的展示效果&#xff0c;主用的编程语言为JavaScript,和前端主流框架bootstrap。 第二层为后端模型设计&#xff0c;编程语言选了简单易懂的python&#xff0c;用Django作为后…

如何远程连接其他电脑?两种常用方法!

在过去&#xff0c;远程控制仅限于那些擅长计算机专业技术的少数人。然而&#xff0c;随着科学技术的不断发展&#xff0c;越来越多的人可以通过各种远程控制软件实现对其他电脑的远程操作。如今&#xff0c;对于普通电脑用户来说&#xff0c;使用自己的电脑远程控制另一台电脑…

前端框架有哪些?

成长路上不孤单&#x1f60a;【14后&#xff0c;C爱好者&#xff0c;持续分享所学&#xff0c;如有需要欢迎收藏转发&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#xff01;&#xff01;&#xff01;&#xff01;&#xff…

【图论】Dijkstra算法求最短路

一、Dijkstra算法简介 Dijkstra算法是由河南荷兰计算机科学家狄克斯特拉(Dijkstra)于1959年提出的,因此又叫狄克斯特拉算法。 二、初识Dijkstra算法 在使用Dijkstra算法求最短路时&#xff0c;需要用到三个辅助数组&#xff1a; v i s x vis_x visx​&#xff1a;布尔数组&…

PostgreSQL技术内幕8:PostgreSQL查询执行器

0.简介 执行器是查询编译和存储引擎之间的连接模块&#xff0c;其负责将优化器输出的执行计划&#xff0c;进行初始化、执行&#xff0c;访问存储引擎并获得最终结果返回&#xff0c;本章主要介绍PG的执行器模型和其执行流程。 执行器的处理模型 常见的执行器的处理模型包含…

海南云亿商务咨询有限公司抖音电商服务的可靠之选

在这个短视频与直播电商风起云涌的时代&#xff0c;抖音作为其中的佼佼者&#xff0c;正引领着新一轮的消费潮流。而在这片充满机遇与挑战的电商蓝海中&#xff0c;海南云亿商务咨询有限公司犹如一颗璀璨新星&#xff0c;凭借其专业的服务与独到的策略&#xff0c;在抖音电商领…

缺失值插补解释:六种插补方法?

目录 一、说明 二、什么是缺失值&#xff0c;为什么会出现缺失值&#xff1f; 2.1 什么是缺失值&#xff1f; 2.2 为什么会出现缺失值&#xff1f; 2.3 缺失数据类型 2.4 为什么要关注缺失值&#xff1f; 三、数据集 四、缺失数据的插值方式 4.1 方法 1&#xff1a;List-wise D…

通过Python库ydata-profiling生成数据分析报告

一&#xff1a;ydata-profiling库的介绍 ydata-profiling是一个强大的 Python 库&#xff0c;它为 Pandas DataFrame 提供了快速的探索性数据分析&#xff08;EDA&#xff09;。它能够自动生成包含详细统计信息的交互式 HTML 报告&#xff0c;使得数据分析变得更加直观和便捷。…

设计模式 -- 中介者模式(Mediator Pattern)

1 问题引出 1.1 智能家庭项 智能家庭包括各种设备&#xff0c;闹钟、咖啡机、电视机、窗帘 等主人要看电视时&#xff0c;各个设备可以协同工作&#xff0c;自动完成看电视的准备工作&#xff0c;比如流程为&#xff1a;闹铃响起->咖啡机开始做咖啡->窗帘自动落下->电…

idea插件【1】Smart Tomcat

一、简介 在开发过程中除了springboot项目支持jar运行&#xff0c;很多场景下需要使用到tomcat外置服务部署&#xff0c;此时我们可以使用idea插件Smart Tomcat &#xff08;Smart Tomcat 插件是一个用于简化与 Tomcat 服务器交互的工具&#xff0c;它提供了一些额外的功能来增…

TCP协议相关特性

TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是互联网传输层协议之一&#xff0c;也是 TCP/IP 协议簇的核心协议。它的作用是在 IP 网络上提供可靠的、面向连接的通信。 TCP基本特点: 有链接,可靠传输, 面向字节流 ,全双工 TCP协议段格…

掌握盈利新技能:网格交易法分享

交易策略对于交易成功至关重要。一个有效的策略可以帮助你在市场中轻松获得盈利&#xff0c;而一个不恰当的策略就可能导致不少损失。今天&#xff0c;我们将来探讨网格交易法&#xff0c;这是一种特别适合震荡市场的交易策略。 什么是网格交易法&#xff1f; 网格交易法&#…

linux下oracle启动及关于pfile和spfile启动参数文件的配置

在现代企业环境中&#xff0c;Oracle数据库作为关键的业务支撑平台&#xff0c;承载着大量的数据处理和事务管理任务。 无论是对于DBA&#xff08;数据库管理员&#xff09;还是开发人员来说&#xff0c;掌握Oracle数据库的基本操作和配置技巧都是至关重要的。本文提供了一份全…

图形语言传输格式glTF和三维瓦片数据3Dtiles(b3dm、pnts)学习

文章目录 3DTilesb3dm一、glTF1.glTF 3D模型格式有两种2.glTF 场景描述结构3.glTF的JSON结构 二、 3DTiles 原文 工具资料 格式详解 格式详解&#xff01; 3D Tiles 是一种开源的、优化的文件格式&#xff0c;支持逐级细节&#xff08;LOD&#xff09;和空间索引&#xff0c;使…

生成模型之训练

如图1所示。生成器和判 别器是两个网络&#xff0c;在训练前我们要先分别进行参数初始化。训练的第一步是固定生成器&#xff0c;只训 练判别器。因为生成器的初始参数是随机初始化的&#xff0c;所以它什么都没有学习到&#xff0c;输入一系列采 样得到的向量给它&#xff0c;…

Qt第三课 ----------widget的控件属性及stylesheet样式(css样式)的简单介绍

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…