目录
前言
行业越来越内卷,我们要不断保持学习热情,不断更新自己的技术栈,在自己的擅长的领域深扎,同时增加知识广度,扩大行业视野和认知,在这里我将和大家一起学习进步。大家可以先关注博主一波,后续继续更新各种技术免费专栏,涉及数据结构与算法,c/c++ QT/duilib等客户端开发,服务器开发,音视频开发,驱动开发,逆向安全,游戏开发等等有关技术栈,还有各种热门编程技术如rust, java,go, javascript, python, php, c#等等,遍及各种平台如android, ios, windows, unix, linux等等,让新手从入门到实战,从IT学习者身份顺利过渡到职场人士 。
一、项目概述
1.1 项目目标
运用所学C语言的基础知识,设计一个密码本,方便解决日常生活中遇到的各类账号密码记录问题。
实现完该项目,大致能巩固C语言的基础知识的应用。对数据类型,各种运算符,控制结构,输入输出,数组和指针,函数结构体,文件读写等有一定的深刻的认识。初学者做项目途中肯定遇到不少问题,通过调试和懂得网上寻找答案也一定能解决。
功能如下:
1)可以安全地保存用户的各种账号密码,并在用户退出后再次打开软件时,准确地恢复这些数据,确保用户不会丢失任何信息。
2)在存储这些敏感数据时,我们会使用一种简单的加密算法来增加数据的安全性,防止未经授权的访问。
3)用户可以根据特定条件快速查找并提取已保存的账号密码数据,方便快捷。
4)同时,用户还可以随时修改已有的账号密码数据,以适应不同的需求或更新个人信息。
1.2 项目开发环境和实现具体功能
本项目居于windows系统环境,采用Visual Studio IDE软件开发(这里不介绍集成环境开发软件的使用),入门的同学也可以自行选择其他的IDE进行编写代码,使用.h和.c(.cpp)文件后缀命名代码文件。
具体功能有:
1)新增密码项
2)删除密码项
3)修改密码项
4)查询密码项
5)保存密码本功能
6)动态修改密码本容量
7)操作密码修改(操作密码是密码本的个人登录密码)
8)使用操作密码登录和退出
9)数据加密功能
10)其他
二、项目实现流程与逻辑
2.1 数据定义部分
把项目中的全局变量、常量、自定义数据类型、宏等,统一定义在 data 文件中(包括data.h 和 data.cpp)。其中密码项里面包含使用站点,用户名账号,密码,备注等数据,我们将其定义为结构体。密码本的容量使用全局变量,由于还没学到c++的类的使用,所以全部代码都是函数模块化,流程化,面向过程编程。
data.h代码如下:
#pragma once
#define 查看所有 1
#define 新增密码 2
#define 删除密码 3
#define 修改密码 4
#define 查询密码 5
#define 保存文本 6
#define 修改操作密码 7
#define 修改容量 8
#define 退出 9
#define NUM 100 //初始密码本容量
typedef struct PASSWORD {
char website[100]; //使用密码的地方
char userName[100];//账号或用户名
char passWord[100];//密码
char note[100];//备注
}PASSWORD, *PPASSWORD;
extern int g_nNum;//当前的密码本容量
data.cpp代码如下:
#include <stdio.h>
#include <stdlib.h>
#include "data.h"
int g_nNum; //当前密码本容量
2.2 界面与用户交互实现
此部分为程序的入口部分,控制界面与用户的交互,并不断的在循环中接收相应用户操作。
程序的入口main函数,定义在myPassword.cpp:
#include <stdio.h>
#include <stdlib.h>
#include "data.h"
#include "ctrl.h"
int main() {
loginOS();//登录 密码本 系统
system("pause");
return 0;
}
操作密码功能和控制界面代码如下(如下代码自行文件命名如ui.cpp):
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"data.h"
#include"ctrl.h"
//读取密码本操作密码
char* readPass(char* str) {
FILE* fp;
if (fopen_s(&fp, "pass.i", "r") != 0) {
printf("第一次使用,初始化文件中!!\n");
//exit(1);
}
else {
fscanf_s(fp, "%s", str, 20);
for (int i = 0; str[i] != '\0'; i++) str[i] ^= 5;//读取解密
fclose(fp);
return str;
}
return NULL;
}
//保存密码本操作密码
void savePass(char * str1) {
FILE* fp;
if (fopen_s(&fp, "pass.i", "w") != 0) {
printf("打开数据失败\n");
system("pause");
exit(1);
}
for (int i = 0; str1[i] != '\0'; i++) str1[i] ^= 5; //写进文件加密
fprintf(fp, "%s", str1);
fclose(fp);
}
//修改密码本操作密码
void modifyPass() {
char str[20];
char* pass = readPass(str);
int flag = 1;
while (flag) {
char str1[20];
printf("原操作密码为:%s\n", pass);
printf("请输入新的操作密码:\n");
scanf_s("%s", str1, 20);
char str2[20];
printf("请再次输入确认密码:\n");
scanf_s("%s", str2, 20);
//gets_s(str2);
if (str1 == "" || str2 == "") { printf("输入为空,修改失败!"); flag = 0; }
else if (strcmp(str1, str2) == 0) {
savePass(str1);
printf("修改成功!");
flag = 0;
}
else { printf("请重新输入\n"); flag = 1; }
}
system("pause");
system("cls");
}
void initPlayPass() {
FILE* fp;
char str[20] = "1234";
if (fopen_s(&fp, "pass.i", "w") != 0) {
printf("打开数据失败\n");
system("pause");
exit(1);
}
for (int i = 0; str[i] != '\0'; i++) str[i] ^= 5;
fprintf(fp, "%s", str);
fclose(fp);
}
//登录界面
void loginOS() {
printf("=====《欢迎使用个人密码本》=====\n");
printf("请使用输入密码本操作密码(初始密码:1234):\n");
char _ch[20];
//scanf_s("%s", _ch, 20);
gets_s(_ch);
char str[20];
if (readPass(str) == NULL) {
initPlayPass();
}
if (strcmp(_ch, readPass(str)) != 0) {
// printf("%s\n", readPass());
printf("密码不正确退出系统!!!\n");
system("pause");
return;
}
system("pause");
system("cls");
printf("登录成功!");
initPassword();
}
//修改密码本容量
void alterVolume(PASSWORD* ppwd, int *ncount) {
printf("原始密码本容量大小为:%d\n", g_nNum);
printf("请输入您想修改的大小:\n");
scanf_s("%d", &g_nNum);
if (g_nNum == 0) { printf("输入为空,修改失败!\n"); return; }
savePwd(ppwd, ncount);
system("pause");
system("cls");
printf("修改成功!");
}
//进入密码本操作界面
void initPassword() {
//PASSWORD pPwd[NUM];
PASSWORD* pPwd = nullptr;
int pnCount = 0;//当前密码个数
g_nNum = 0;//当前密码本容量
PASSWORD * ppPwd = readPwd(pPwd, &pnCount);//初始化密码本
//readPwd(pPwd, &pnCount);
printf("当前密码个数:%d\n", pnCount);
printf("当前容量:%d\n", g_nNum);
int flag = 1;
while (flag) {
printf("================================================\n");
printf("1 查看全部密码 2 新增密码 3 删除密码\n");
printf("4 修改密码 5 查询密码 6 保存文本\n");
printf("7 修改操作密码 8 修改容量 9 退出\n");
printf("请输入您的操作选项:\n");
printf("================================================\n");
int option;
scanf_s("%d", &option);
//char character = getchar();
//int option = character - '0';
while ('\n' != getchar()) { fflush(stdin); };
switch (option) {
case 查看所有:
searchAllPwd(ppPwd, pnCount);
break;
case 新增密码:
insertPwd(ppPwd, &pnCount);
break;
case 删除密码:
deletePwd(ppPwd, &pnCount);
break;
case 修改密码:
alterPwd(ppPwd, &pnCount);
break;
case 查询密码:
searchPwd(ppPwd, pnCount);
break;
case 保存文本:
savePwd(ppPwd, &pnCount);
break;
case 修改操作密码:
modifyPass();
break;
case 修改容量:
alterVolume(ppPwd, &pnCount);
break;
case 退出:
flag = 0;
printf("谢谢使用\n");
break;
default:
flag = 0;
printf("输入错误,自动退出!\n");
break;
}
}
}
2.3 逻辑控制实现
对应用户不同的操作,分别定义不同的函数进行处理。基本的密码增删改查功能都在ctrl.h和ctrl.cpp文件。操作密码保存在pass.i文件,密码条数,和密码本容量及各种密码数据保存在data.i文件。
ctrl.h文件代码:
#pragma once
//查看所有密码
void searchAllPwd(PASSWORD* pwd, int pnCount);//查看所有站点密码信息
void insertPwd(PASSWORD* pwd, int * pnCount);//插入密码信息
void deletePwd(PASSWORD* pwd, int * pnCount);//删除密码
void alterPwd(PASSWORD* pwd, int* pnCount);//修改密码
void searchPwd(PASSWORD* pwd, int pnCount);//查询密码
void savePwd(PASSWORD * pwd, int *pnCount);//保存密码
PASSWORD* readPwd(PASSWORD * ppwd, int *pnCount);//初始化读取一些密码本数据
void savePass(char * str1); //保存个人密码本的操作密码
void modifyPass();//修改个人密码本的操作密码
void loginOS();//用操作密码登录密码本
void alterVolume(PASSWORD* ppwd, int *pnCount);//密码本扩容
void initPassword();//进入密码本系统
void initPlayPass();//初始化操作密码
上面一些函数的参数列表近乎相同,有些函数需要传递指针而有些不需要。传递指针的目的是为了函数在内部改变这个变量的值。
ctrl.cpp文件代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include"data.h"
#include"ctrl.h"
//查询所有密码,参数为密码本类型指针,当前密码个数
void searchAllPwd(PASSWORD* pPwd, int nCount) {
printf("=========您查询的结果一共返回以下 %3d 条记录=========\n", nCount);
for (int i = 0; i < nCount; i++) {
printf("--ID: %d-------------------\n", i);
printf("目标:%s \n", pPwd[i].website);
printf("用户名:%s \n", pPwd[i].userName);
printf("密码:%s \n", pPwd[i].passWord);
printf("备注:%s \n", pPwd[i].note);
}
printf("\n");
system("pause");
system("cls");
}
//插入密码,参数为密码本类型指针,当前密码个数的指针
void insertPwd(PASSWORD* pPwd, int * pnCount) {
int i = *pnCount;
if (i < 0 || i >= g_nNum) {
printf("插入位置异常: %d \n", i);
return;
}
char website[200];
char userName[200];
char passWord[200];
char note[200];
printf("请输入<目标站点>:\n");
//scanf_s("%s",website,200);
gets_s(website); //可以带有空格输入
printf("请输入<用户名>:\n");
gets_s(userName);
//scanf_s("%s",userName,200);
printf("请输入<密码>:\n");
gets_s(passWord);
//scanf_s("%s",passWord, 200);
printf("请输入<备注信息>:\n");
gets_s(note);
//scanf_s("%s",note, 200);
strcpy_s(pPwd[i].website, strlen(website) + 1, website);
strcpy_s(pPwd[i].userName, strlen(userName) + 1, userName);
strcpy_s(pPwd[i].passWord, strlen(passWord) + 1, passWord);
strcpy_s(pPwd[i].note, strlen(note) + 1, note);
(*pnCount)++;
savePwd(pPwd, pnCount);
printf("\n");
system("pause");
system("cls");
}
//删除密码,参数为密码本类型指针,当前密码个数的指针
void deletePwd(PASSWORD* pPwd, int * pnCount) {
int i = -1;
int flag = 1;
while (flag) {
getchar();
printf("请输入待删除项<密码ID>\n");
scanf_s("%d", &i);
if (i < 0 || i >= *pnCount) {
printf("删除位置异常: %d \n", i);
return;
}
getchar();
printf("请确认是否删除!(y是n否):\n");
char dele = getchar();
if (dele == 'y' || dele == 'Y') {
for (size_t j = i; j < *pnCount - 1; j++) {
//pPwd[j] = pPwd[j + 1];
strcpy_s(pPwd[j].website, strlen(pPwd[j + 1].website) + 1, pPwd[j + 1].website);//复制目标,复制长度,复制源
strcpy_s(pPwd[j].userName, strlen(pPwd[j + 1].userName) + 1, pPwd[j + 1].userName);
strcpy_s(pPwd[j].passWord, strlen(pPwd[j + 1].passWord) + 1, pPwd[j + 1].passWord);
strcpy_s(pPwd[j].note, strlen(pPwd[j + 1].note) + 1, pPwd[j + 1].note);
}
(*pnCount)--;
savePwd(pPwd, pnCount);
printf("修改成功!\n");
printf("\n");
flag = 0;
}
else if (dele == 'n' || dele == 'N') { flag = 0; printf("退出\n"); }
else {
printf("输入错误,请重新输入!\n");
flag = 0;
}
system("pause");
system("cls");
}
}
//修改密码,参数为密码本类型指针,当前密码个数的指针
void alterPwd(PASSWORD* pPwd, int* pnCount) {
int i = -1;
int flag = 1;
while (flag) {
getchar();
printf("请输入待修改项<密码ID>\n");
scanf_s("%d", &i);
if (i < 0 || i >= *pnCount) {
printf("修改位置异常: %d \n", i);
return;
}
printf("--ID: %d-------------------\n", i);
printf("目标:%s \n", pPwd[i].website);
printf("用户名:%s \n", pPwd[i].userName);
printf("密码:%s \n", pPwd[i].passWord);
printf("备注:%s \n", pPwd[i].note);
printf("~修改~\n");
getchar();
printf("请确认是否修改!(y是n否):\n");
char modi = getchar();
if (modi == 'y' || modi == 'Y') {
PASSWORD pass;
printf("请输入<目标站点>\n");
// scanf_s("%s", pass.website, 100);
getchar();
gets_s(pass.website);
strcpy_s(pPwd[i].website, strlen(pass.website) + 1, pass.website);
printf("请输入<用户名>\n");
// scanf_s("%s", pass.userName, 100);
gets_s(pass.userName);
strcpy_s(pPwd[i].userName, strlen(pass.userName) + 1, pass.userName);
printf("请输入<密码>\n");
// scanf_s("%s", pass.passWord, 100);
gets_s(pass.passWord);
strcpy_s(pPwd[i].passWord, strlen(pass.passWord) + 1, pass.passWord);
printf("请输入<备注信息>\n");
// scanf_s("%s", pass.note, 100);
gets_s(pass.note);
strcpy_s(pPwd[i].note, strlen(pass.note) + 1, pass.note);
savePwd(pPwd, pnCount);
flag = 0;
printf("修改成功!\n");
}
else if (modi == 'n' || modi == 'N') {
flag = 1;
printf("退出!!\n");
}
else {
printf("输入错误,请重新操作!!\n");
flag = 1;
}
}
printf("\n");
system("pause");
system("cls");
}
//查询某密码,参数为密码本类型指针,当前密码个数
void searchPwd(PASSWORD* pPwd, int nCount) {
char key[100] = { 0 };
printf("请输入查找密码的关键字:\n");
scanf_s("%s[^\n]", key, 100);
int findPwd[100] = { 0 };
int nfindCount = 0;
for (size_t i = 0; i < nCount; i++) {
if (strcmp(pPwd[i].website, key) == 0) {
findPwd[nfindCount++] = i;
continue;
}
else if (strcmp(pPwd[i].userName, key) == 0) {
findPwd[nfindCount++] = i;
continue;
}
else if (strcmp(pPwd[i].passWord, key) == 0) {
findPwd[nfindCount++] = i;
continue;
}
else if (strcmp(pPwd[i].note, key) == 0) {
findPwd[nfindCount++] = i;
continue;
}
else printf("查找不到匹配项\n");
}
printf("======共计匹配:%3d 条记录==================\n", nfindCount);
for (size_t i = 0; i < nfindCount; i++) {
int pos = findPwd[i];
printf("--ID: %3d-------------------\n", i);
printf("目标:%s \n", pPwd[i].website);
printf("用户名:%s \n", pPwd[i].userName);
printf("密码:%s \n", pPwd[i].passWord);
printf("备注:%s \n", pPwd[i].note);
printf("\n");
system("pause");
system("cls");
}
}
//保存整个密码本数据,参数为密码本类型指针,当前密码个数的指针
void savePwd(PASSWORD* pPwd, int* pnCount) {
FILE* pFile;
int ret = 0;
ret = fopen_s(&pFile, "data.i", "wb");
if (ret != 0) { printf("打开文件失败!"); return; }
printf("当前保存的个数是:%d\n", *pnCount);
fwrite(pnCount, sizeof(int), 1, pFile);
fwrite(&g_nNum, sizeof(int), 1, pFile);
int byteSize = sizeof(PASSWORD)* g_nNum;
char* buf = (char*)malloc(byteSize);
memcpy_s(buf, byteSize, pPwd, byteSize);
for (size_t i = 0; i < byteSize; i++) { //加密
buf[i] ^= (i + *pnCount + g_nNum);
//buf[i] ^= 5;
}
//g_nNum = nCount;
size_t rlen = fwrite(buf, sizeof(PASSWORD), g_nNum, pFile);
if (rlen != g_nNum) {
printf("写入文件密码错误\n");
}
else { printf("写入成功!!\n"); }
fclose(pFile);
free(buf);
}
//初始化读取密码本数据,返回值为密码本类型指针,参数为密码本类型指针,当前密码个数的指针
PASSWORD* readPwd(PASSWORD *pPwd, int* pnCount) {
FILE* pFile;
errno_t err = fopen_s(&pFile, "data.i", "rb");
if (err != 0) {//打开失败
pPwd = (PASSWORD*)malloc(sizeof(PASSWORD)*NUM);//定义密码本堆空间
g_nNum = NUM;
return pPwd;
}
g_nNum = NUM;
fread(pnCount, sizeof(int), 1, pFile);//当前密码个数
//if (pnCount == nullptr) { pnCount = 0; }
int ss = sizeof(g_nNum);
fread(&g_nNum, sizeof(int), 1, pFile);//当前密码本容量个数
if (g_nNum <= 0) {
g_nNum = NUM;
}
pPwd = (PASSWORD*)malloc(sizeof(PASSWORD)*g_nNum);//定义密码本堆空间
memset(pPwd, 0, sizeof(PASSWORD)*g_nNum);//初始化堆空间
size_t rlen = fread_s(pPwd, sizeof(PASSWORD)*g_nNum, sizeof(PASSWORD), g_nNum, pFile);//读取密码数组
if (rlen != g_nNum) {
printf("读取文件密码错误或者文件为空\n");
fclose(pFile);
return pPwd;
}
int byteSize = sizeof(PASSWORD)*g_nNum;
char* buf = (char*)pPwd;//加密数组
for (size_t i = 0; i < byteSize; i++) { //解密
buf[i] ^= (i + *pnCount + g_nNum);
//buf[i] ^= 5;
}
pPwd = (PASSWORD*)buf;//转密码本数组
fclose(pFile);
return pPwd;
}
三、运行截图和参考项目
1)使用初始操作密码登录
2)登录后的用户界面
3)登录后修改操作密码
4)修改密码本容量大小
5)密码本全部密码项查询
6)删除某个密码项
7)修改密码项
修改成功后
8)重新载入程序,查询数据
截图略
源码程序下载:https://download.csdn.net/download/linshantang/88603631
没积分下载的朋友,可以关注私聊获取,谢谢