【第十四节】C语言小项目(windows控制台版本密码本)

目录

 前言

一、项目概述

1.1 项目目标

1.2 项目开发环境和实现具体功能

二、项目实现流程与逻辑

2.1 数据定义部分

2.2 界面与用户交互实现

2.3 逻辑控制实现

三、运行截图和参考项目


 前言

        行业越来越内卷,我们要不断保持学习热情,不断更新自己的技术栈,在自己的擅长的领域深扎,同时增加知识广度,扩大行业视野和认知,在这里我将和大家一起学习进步。大家可以先关注博主一波,后续继续更新各种技术免费专栏,涉及数据结构与算法,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

没积分下载的朋友,可以关注私聊获取,谢谢

  • 17
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

攻城狮7号

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值