首先声明,个人水平有限,这只是程序作业自己写的,只作为个人记录。其次,本人并没有学C++,只能采用c来写。最后,注释都在代码里面了,不细说了,大概功能和思路都有了,然后文件的位置记得改成自己的,这个用了三个文件(以后需要补充再说吧)
一、要求
2 功能要求
2.1 基本要求
系统具有以下基本功能:
(1) 注册:每个进入系统的人员需注册,管理员不用
(2) 查询功能:可以查阅参选对象的信息
当前投票状态
参选对象 票数 排名 百分比
(3) 管理人员可以查看注册信息
用户名 手机号 投票次数
(4) 提供菜单选项,设置用户角色,管理员和注册用户、参选对象:
管理员:审核参选对象;可以修改投票次数的限定、选举时间限定;发布、统计投票结果;
用户:查询投票情况,搜索参选对象,投票。
(5)对用户的输入进行一定的正确性检查。
(6)手机一天投票数量限制。比如:同意个手机号码一天只能投一次,或者一天只能给一个参选者投一次票。
二、内容(已经带了注释)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<conio.h>
#include<ctype.h>
#include<time.h>
#include "Menu.h"//菜单的头文件
#define NUM 50//50个人的容量
#pragma warning(disable:4996)//scanf的报错
/*结构体1,负责存储用户的数据*/
typedef struct ID1 {
char name[8]; /*姓名*/
char phone[12]; /*号码 */
int ticket; /*现有票数*/
int sign; /*投票次数限定*/
}ID1;//用户
ID1 id1[NUM];
/*结构体2,负责存储参选对象的数据*/
typedef struct ID2 {
int rank; /*排名*/
int number; /*编号 */
char name[8]; /*姓名*/
int ticket; /*票数 */
char phone[12]; /*号码 */
}ID2;//参选人
ID2 id2[NUM];
/*结构体3,负责存储系统时间*/
typedef struct TIME {
int year; //年
int mouth; //月
int day; //日
}TIME;
TIME timec[2];
void Admin(int, int);/*管理员函数*/
void insert2(int*); /*用户注册函数*/
void changesign(int count1);//改变投票限定次数的函数
void changetime(TIME timec[]);/*改变时间的函数*/
void systeamtime(int n, int count2);/*获得系统时间的函数*/
void timefile(TIME timec[]);/*读取文本里面的时间限制的函数*/
int ReadFile3(ID2 id2[]);/*读取参选人数量的函数*/
int ReadFile4(ID1 id1[]);/*读取用户人数*/
void TICKET(int n, int count2);/*用户投票函数*/
void dispFile(const char* fileName);/*获得指定文本里面的数据并且打印出来*/
void WriteFile3(ID2 id2[], int n);/*以w的方式,改变参选人票数的函数*/
void WriteFile4(ID1 id1[], int n);/*同3,改的是用户的票数*/
void WriteFile5(ID2 id2[], int n);/*用于管理员审核参选人时的读写函数*/
void Candidate(int);/*参选人函数*/
void insert1(int*); /*参选人注册函数*/
void secretword(char key[]);/*密码加密函数*/
void DEL();/*管理员删除参选人函数*/
void SortRank(ID2 id2[], int n);/*排名的函数*/
void ReadFile1(ID1 id1[]);/*这个是读取用户文本里面的数据赋给用户的结构体*/
void ReadFile2(ID2 id2[]);/*这个是读取参选人文本里面的数据赋给参选人的结构体*/
void Voter(int, int);/*用户函数*/
int main()
{
int i;//菜单选择
do { //菜单界面
int count1 = ReadFile4(id1);//记录用户个数
int count2 = ReadFile3(id2);//记录参选人个数
/*并且放到while里面确保实时更新数据*/
mainMenu();//主菜单的显示
scanf_s("%d", &i);//做出选择
switch (i)
{
case 1:Admin(count1, count2); /*管理员函数 */
break;
case 2:Candidate(count2); /*参选人函数*/
break;
case 3:Voter(count1, count2); /*用户函数 */
break;
case 4:insert1(&count2); /*参选人注册函数 */
break;
case 5:insert2(&count1); /*用户注册函数 */
break;
case 6:break; /*退出系统 */
default:printf_s("错误选择!请重新选择\n");
break;
}
} while (i != 6);
return 0;
}
void Admin(int count1, int count2)/*管理员*/
{
int adminname,i;//第一个是账号,第二个是选择菜单
char password[4];//定义一个字符串来放输入值
char key[4] = {"666"};//设定管理员密码
printf_s("请输入管理员账号:");
scanf("%d", &adminname);
if (adminname == 666) { /*管理员账号核验*/
printf_s("请输入管理员密码:");
//scanf("%s", &password);
secretword(password);//以*号的方式输入密码
if (strcmp(password,key)==0) { /*管理员密码核验*/
do {
adminMenu();//管理员菜单显示
scanf_s("%d", &i);/*接收菜单选择*/
switch (i)
{
case 1:changesign(count1);/*调用修改投票次数运算 */
break;
case 2:changetime(timec);/*调用修改选举时间函数 */
break;
case 3:printf("排名 编号 姓名 票数 号码\n");
dispFile("E:\\ID2.txt");/*显示参选人信息 +审核参选人*/
DEL();
break;
case 4:printf("用户名 手机号 投票次数 sign\n");
dispFile("E:\\ID1.txt");/*显示用户信息 */
break;
case 5:printf("排名 编号 姓名 票数 号码\n");
dispFile("E:\\ID2.txt");/*显示参选人信息*/
break;
case 6:break;/*退出系统 */
default:printf_s("重新选择\n");
break;
}
} while (i != 6);
return;
}
else {
printf_s("密码错误!\n");
return;
}
}
else {
printf_s("用户名错误!\n");
return;
}
}
void Candidate(int count2)/*参选人系统*/
{
int i, n;//count2存放参选人有几个
char phone[12];//存放电话的字符数组
CandidateMenu();//菜单
ReadFile2(id2);//对参选人结构体赋值
scanf("%s", &phone);//输入电话
for (i = 0; i < count2; i++)/*查找是否存在记录 */
if (strcmp(id2[i].phone, phone) == 0)//核验电话正确
{
printf("欢迎%s", id2[i].name);//欢迎参选人
do {
printf_s("查看其他参选人,请输入1:\n退出请输入2:");
scanf_s("%d", &n);//选择
switch (n)
{
case 1:printf("排名 编号 姓名 票数 号码\n");
dispFile("E:ID2.txt");//显示所有参选人的数据
break;
case 2:break;//退出参选人系统
default:printf_s("错误选择!请重选\n");
break;
}
} while (n != 2);
return;
}
printf_s("手机号不存在!\n");//如果输入号码有问题,则显示手机号码不存在
return;
}
void Voter(int count1, int count2)/*用户*/
{
int i, n, j;//i用于循环,n是菜单,j用于系统时间获取函数
char phone[12];//电话数组
VoterMenu();//用户界面菜单
ReadFile1(id1);//读取用户文件的数据放入用户结构体中
scanf("%s", &phone);//输入电话号码
for (i = 0; i < count1; i++)//查找是否存在记录。count1是用户数量
if (strcmp(id1[i].phone, phone) == 0)//电话核验
{
j = i;
do {
printf_s("查看参选人,请输入1:\n投票请输入2:\n退出请输入3:");
scanf_s("%d", &n);//菜单选择
switch (n)
{
case 1:printf("排名 编号 姓名 票数 号码\n");
dispFile("E:ID2.txt");//查看参选人数据
break;
case 2:systeamtime(j,count2);
//获得系统时间,并且投票函数位于该函数内,此处功能为投票,且不在投票时间内,会有错误提示
break;
case 3:break;//推出用户系统
default:printf_s("错误选择!请重选\n");
break;
}
} while (n != 3);
return;
}
printf_s("手机号不存在!\n");//手机号输入判断
return;
}
void insert1(int* count2)/*参选人注册*/
{
int i = 0;//用于循环
char in_phone[12], name[8];//电话和名字字符数组
if (*count2 == NUM)//上限50人
{
printf_s("空间已满!");
return;
}
insertMenu1();//用户注册菜单显示
scanf("%s", &in_phone);//输入手机号
if (strlen(in_phone) != 11)//判断是否为11位
{
printf("非法输入");
return;
}
ReadFile2(id2);//读取id2文件2数据放入结构体
for (i = 0; i < *count2; i++){
if (strcmp(id2[i].phone, in_phone) == 0)//校验手机是否存在
{
printf_s("手机号已存在!\n");//手机号若存在,直接退出
return;
}
}
printf_s("请输入用户名:");
scanf("%s", &name);
id2[i].number = i;
id2[i].ticket = 0;
id2[i].rank = *count2;
FILE* fp;
fp = fopen("E:\\ID2.txt", "a");
fprintf(fp, "%d %4d %4s %4d %14s\n", id2[i].rank, id2[i].number, name, id2[i].ticket, in_phone);
fclose(fp);
printf_s("参选人注册成功!\n");
return;
}
void insert2(int* count1)/*用户插入 */
{
int i=0;//用于循环
char in_phone[12] ,name[12];//一样是名字和电话字符数组来存数据
if (*count1 == NUM)//50人上限
{
printf_s("空间已满!");
return;
}
insertMenu2();
scanf("%s",&in_phone);
if (strlen(in_phone) != 11)//确认号码是不是11位
{
printf("非法输入");
return;
}
ReadFile1(id1);
for (i = 0;i<*count1; i++)//从当前用户文本里面拿数据
{
if (strcmp(in_phone,id1[i].phone) == 0)//判断有没有手机号码,要是有,则注册失败
{
printf_s("手机号已存在!");
return;
}
}
printf_s("请输入用户名:");
scanf("%s", &name);//输入用户名
id1[i].ticket = 6;//默认票数为6
id1[i].sign = 0;//默认没有投票
FILE* fp;
fp = fopen("E:\\ID1.txt", "a");
fprintf(fp, "%s %18s %5d %5d\n", name, in_phone, id1[i].ticket, id1[i].sign);
fclose(fp);
printf_s("用户注册成功!\n");
return;
}
/*read1是把用户数据拿出来放进当前结构体,read2是把参选人数据放进参选人结构体*/
void ReadFile1(ID1 id1[])
{
int i = 0;
FILE* fp;
fp = fopen("E:\\ID1.txt", "r");
if (fp == 0)
{
printf("error\n");
exit(1);
}
fscanf(fp, "%s%s%d%d", id1[i].name, id1[i].phone, &id1[i].ticket, &id1[i].sign);
while (!feof(fp))
{
i++;
fscanf(fp, "%s%s%d%d", id1[i].name, id1[i].phone, &id1[i].ticket, &id1[i].sign);
}
fclose(fp);
}
void ReadFile2(ID2 id2[])
{
int i = 0;
FILE* fp;
fp = fopen("E:\\ID2.txt", "r");
if (fp == 0)
{
printf("error\n");
exit(1);
}
fscanf(fp, "%d %d %s %d %s", &id2[i].rank, &id2[i].number, id2[i].name, &id2[i].ticket, id2[i].phone);
while (!feof(fp))
{
i++;
fscanf(fp, "%d %d %s %d %s", &id2[i].rank, &id2[i].number, id2[i].name, &id2[i].ticket, id2[i].phone);
}
fclose(fp);
}
void SortRank(ID2 id2[], int n)//第一个是排名文件,第二个数量,也就是参选人几个人
{
int i, j, k;
ID2 temp;
for (i = 0; i < n - 1; i++)//简单选择法排序
{
k = i;//k保存本次最大分数的结构体下标
for (j = i + 1; j < n; j++)
if (id2[j].ticket > id2[k].ticket)//比较结构体中的票数
k = j;//找出最大的票数下标
if (k != i)//若最高记录不到,则交换
{
temp = id2[i];
id2[i] = id2[k];
id2[k] = temp;
}
}//排序结束
id2[0].rank = 1;//记录第一
for (i = 1; i < n; i++)//求其他名次
{
if (id2[i].ticket == id2[i - 1].ticket)//若票数一样,则名次相同
id2[i].rank = id2[i - 1].rank;
else
id2[i].rank = i + 1;//否则加1
}
}
void dispFile(const char* fileName)//这个就是打印的文件名
{
char c;//定义一个变量
FILE* fp;
if ((fp = fopen(fileName, "r")) == NULL)//文件打开失败
{
printf("error!\n");
exit(0);
}
while ((c = fgetc(fp)) != EOF)//开始执行循环,打印数据,一直到数据为0,退出循环
{
putchar(c);
}
fclose(fp);
}
void TICKET(int j, int count2)
{
int num, i, flag = 1;//num是编号,i是循环,flag是
if (id1[j].sign == 0)//若次数使用完毕,则投票失败
{
printf_s("你的手机号的投票次数已经使用完毕,\n您已投票,不可再投票!\n");
}
else
{
ReadFile2(id2);//打开参选人数据放入结构体
int count1=ReadFile4(id1);
if (id1[j].ticket == 0)//票数核验,避免出现票数为0的bug
{
printf("你已经没有票了,无法继续投票!\n");
return;
}
printf_s("请输入参选人编号:");
scanf_s("%d", &num);//编号
for (i = 0; i < count2; i++)//查找
{
if (id2[i].number == num)//匹配
{
id2[i].ticket = id2[i].ticket + 1;//参选人加一
id1[j].ticket = id1[j].ticket - 1;//用户减一
id1[j].sign--;//投票次数减少
flag = 0;
printf_s("投票成功!\n");
}
WriteFile4(id1, count1);//id1的票数改变
WriteFile3(id2, count2);//id2的票数也改变
}
if (flag)
printf_s("不存在该参选人!!!\n");//若没有投票成功,则报错
}
}
void WriteFile3(ID2 id2[], int n)//n就是人数
//这个是在投票之后改变id2的票数和排名之后,重新排序,再重新读写,把新数据覆盖到文本里面
{
int i;//循环变量
SortRank(id2,n);//对id2这个结构体进行排序,n是数量
FILE* fp;
fp = fopen("E:\\ID2.txt", "w");//w的读写方式为覆盖
if (fp == 0)
{
printf("error\n");
exit(1);
}
for (i = 0; i < n; i++)
{
//fprintf(fp, "%d %d %s %d %s\n", id2[i].rank, id2[i].number, id2[i].name, id2[i].ticket, id2[i].phone);
fprintf(fp, "%d %4d %4s %4d %14s\n", id2[i].rank, id2[i].number, id2[i].name, id2[i].ticket, id2[i].phone);
}
fclose(fp);
}
void WriteFile4(ID1 id1[], int n)//n还是数量
//这个跟Writefile3一样,只不过操作对象是id1
{
int i;
FILE* fp;
fp = fopen("E:\\ID1.txt", "w");
if (fp == 0)
{
printf("error\n");
exit(1);
}
for (i = 0; i < n; i++)
{
//fprintf(fp, "%s %s %d %d\n", id1[i].name, id1[i].phone, id1[i].ticket, id1[i].sign);
fprintf(fp, "%s %18s %5d %5d\n", id1[i].name, id1[i].phone, id1[i].ticket, id1[i].sign);
}
fclose(fp);
}
void DEL()//管理员的审核函数,用于删除参选人
{
int i;
char phone[12];//定义一个字符数组存电话号码
//ReadFile2(id2);//把参选人数据拿出来给结构体
int count2 = ReadFile3(id2);//读取人数,其实只要这个就行,上面那个都不需要了
printf("请输入操作对象的号码");
scanf("%s", &phone);//输入号码
for (i = 0; i < count2; i++)//循环,对参选人的所有人查找
{
if (strcmp(id2[i].phone, phone) == 0)//若输入
{
WriteFile5(id2, i);
printf("对象已经删除");
return;
}
}//这里可以添加一个审核,就是没有这个对象,然后输入正确的判断
printf("没有执行操作,可能是输入不对,或者是不存在该对象\n");//我确实补了
return;
}
void WriteFile5(ID2 id2[], int n)//这个是用于管理员审核的文件重新读写函数
{
int i, x;//x存总数量,n是要操作对象的位置
x = ReadFile3(id2);
FILE* fp;
fp = fopen("E:\\ID2.txt", "w");//以覆盖的方式
if (fp == 0)
{
printf("error\n");
exit(1);
}
for (i = 0; i < n; i++)
{
//fprintf(fp, " %d %d %-8s\t %d %s\n", id2[j].rank, id2[j].number, id2[j].name, id2[j].ticket, id2[j].phone);
fprintf(fp, "%d %4d %4s %4d %14s\n", id2[i].rank, id2[i].number, id2[i].name, id2[i].ticket, id2[i].phone);
}
for (i = n+1; i < x; i++)
{
//fprintf(fp, " %d %d %-8s\t %d %s\n", id2[j].rank, id2[j].number, id2[j].name, id2[j].ticket, id2[j].phone);
fprintf(fp, "%d %4d %4s %4d %14s\n", id2[i].rank, id2[i].number, id2[i].name, id2[i].ticket, id2[i].phone);
}
fclose(fp);
}
int ReadFile3(ID2 id2[])//读取id2文件人数,即读取参选人数量
{
int i = 0;
FILE* fp;
fp = fopen("E:\\ID2.txt", "r");
if (fp == 0)
{
printf("error\n");
exit(1);
}
fscanf(fp, "%d %d %s %d %s", &id2[i].rank, &id2[i].number, id2[i].name, &id2[i].ticket, id2[i].phone);
while (!feof(fp))
{
i++;
fscanf(fp, "%d %d %s %d %s", &id2[i].rank, &id2[i].number, id2[i].name, &id2[i].ticket, id2[i].phone);
}
fclose(fp);
return i;
}
int ReadFile4(ID1 id1[]) // 读取id1文件人数,即读取用户数量
{
int i = 0;
FILE* fp;
fp = fopen("E:\\ID1.txt", "r");
if (fp == 0)
{
printf("error\n");
exit(1);
}
fscanf(fp, "%s%s%d%d", id1[i].name, id1[i].phone, &id1[i].ticket, &id1[i].sign);
while (!feof(fp))
{
i++;
fscanf(fp, "%s%s%d%d", id1[i].name, id1[i].phone, &id1[i].ticket, &id1[i].sign);
}
fclose(fp);
return i;
}
void systeamtime(int j, int count2)//获取系统时间
{
time_t timep;//这个是time.h文件里面的函数,获取系统世界,返回值为从1970到现在的秒数
struct tm t;//时间结构体,为限制时间的起点和终点
time(&timep);
localtime_s(&t, &timep);
//此函数获得t结构体的时间,已经把
int yearnow = 1900+t.tm_year;//因为算法是有一个起止的,所以要加
int monnow = 1+t.tm_mon;
int daynow = t.tm_mday;
timefile(timec);
if (timec[0].year <= yearnow && yearnow <= timec[1].year)//若当前系统年数不在范围,失败
{
if (timec[0].mouth <= monnow && monnow <= timec[1].mouth)//若不在月份范围,失败
{
if (timec[0].day <= daynow && daynow <= timec[1].day)//若不在天数内,失败
{
TICKET(j,count2);//若以上都可以,则可以进入投票系统
}
else//若不符合,直接提醒不在时间内
{printf("当前时间不在投票时间内!");}
}
else
{printf("当前时间不在投票时间内!");}
}
else
{printf("当前时间不在投票时间内!"); }
}
void changetime(TIME timec[])//把时间范围放入文本
{
int year=0, mon=0, day=0, year2=0, mon2=0, day2=0,i = 0;//先默认为0
printf("请输入要更改的时间起点(年月日)");
scanf("%d%d%d",&year,&mon,&day);
timec[0].year = year;/*插入数据 */
timec[0].mouth = mon;
timec[0].day = day;
printf("请输入要更改的时间终点(年月日)");
scanf("%d%d%d", &year2, &mon2, &day2);
timec[1].year = year2;/*插入数据 */
timec[1].mouth = mon2;
timec[1].day = day2;
FILE* fp;
fp = fopen("E:\\time.txt", "w");
if (fp == 0)
{
printf("error\n");
exit(1);
}
fprintf(fp, "%d %d %d\n",timec[0].year, timec[0].mouth, timec[0].day);
fprintf(fp, "%d %d %d\n", timec[1].year, timec[1].mouth, timec[1].day);
fclose(fp);
}
void timefile(TIME timec[])//读写文件里面的设定时间
{
int i = 0;
FILE* fp;
fp = fopen("E:\\time.txt", "r");
if (fp == 0)
{
printf("error\n");
exit(1);
}
fscanf(fp, "%d %d %d", &timec[i].year, &timec[i].mouth, &timec[i].day);
while (!feof(fp))
{
i++;
fscanf(fp, "%d %d %d", &timec[i].year, &timec[i].mouth, &timec[i].day);
}
fclose(fp);
}
void secretword(char key[]) {
unsigned char c;
int i = 0;
while ((c = getch()) != '\r') {
if (i < 20 && isprint(c)) {
key[i] = c;
i++;
putchar('*');
}
else if (i > 0 && c == '\b') {
i--;
putchar('\b');
putchar(' ');
putchar('\b');
}
}
printf("\n");
key[i] = '\0';
}
void changesign(int count1)//把变化后的限定次数写进文件里面
{
int SIGN,i;
printf("请输入你所要限定的投票次数");
scanf("%d",&SIGN);//输入限定次数
FILE* fp;
fp = fopen("E:\\ID1.txt", "w");
if (fp == 0)
{
printf("error\n");
exit(1);
}
for (i = 0; i < count1; i++)
{
//fprintf(fp, "%s %s %d %d\n", id1[i].name, id1[i].phone, id1[i].ticket, id1[i].sign);
fprintf(fp, "%s %18s %5d %5d\n", id1[i].name, id1[i].phone, id1[i].ticket, SIGN);
}
fclose(fp);
printf("修改成功");
}
三、菜单界面(h头文件)
请自行更改
#include <stdlib.h>
#include <stdio.h>
//void mainMenu()
//{
// printf_s("|投票系统|\n");
// printf_s("\n");
// printf_s("1-管理员\n");
// printf_s("2-参选人\n");
// printf_s("3-用户\n");
// printf_s("4-注册参选账户\n");
// printf_s("5-注册用户\n");
// printf_s("6-退出\n");
// printf("请输入你的选择");
//}
//
//void adminMenu()
//{
// /*显示一个简易菜单 */
// printf_s("|管理员系统|\n");
// printf_s("\n");
// printf_s(" 1-修改投票次数\n");
// printf_s(" 2-修改选举时间\n");
// printf_s(" 3-审核参选人信息\n");
// printf_s(" 4-显示用户信息\n");
// printf_s(" 5-发布投票结果\n");
// printf_s(" 6-退出\n");
//}
//void CandidateMenu()
//{
// printf_s("|参选人信息系统|\n");
// printf_s("\n");
// printf_s("请输入手机号:");
//}
//void VoterMenu()
//{
// printf_s("|用户投票系统|\n");
// printf_s("\n");
// printf_s("请输入手机号:");//用户登陆,补一个密码
//}
//void insertMenu1()
//{
// printf_s("|参选人注册系统|\n");
// printf_s("\n");
// printf_s("请输入手机号:");
//}
//void insertMenu2()
//{
// printf_s("|用户注册系统|\n");
// printf_s("\n");
// printf_s("请输入手机号:");
//}