工资信息采用结构体数组:
Struct Salary_Info
{
int Card_No; //工资卡号
Char name[20]; //姓名
int month; //月份
float Init_Salary; //应发工资
float Water_Rate; //水费
float Electric_Rate; //电费
float tax; //税金
float Final_Salary; //实发工资
}SI[MAX]; //SI[MAX]中每个数组元素对应一个职工工资信息
(1)主函数提供输入、处理和输出部分的函数调用,各功能模块采用菜单方式选择。
(2)输入模块
按照工资卡号、姓名、月份、应发工资、水费、电费的顺序输入信息,税金和实发工资根据输入的信息进行计算得到,这些信息被录入到文件中。
文件操作函数:fopen,fwrite,fclose.
税金的计算:
if(应发工资<=800)
税金=0;
else if (应发工资>800&&应发工资<=1400)
税金=(应发工资-800)*5%;
else if (应发工资>1400)
税金=(应发工资-1400)*10%;
实发工资=应发工资-水费-电费-税金。
(3)添加模块
增加新的职工工资信息,从键盘输入并逐条写到原来的输入文件中,采用追加而不是覆盖的方式(以”ab”方式打开文件)。
(4)浏览模块
分屏显示职工工资信息,可以指定10个1屏,按任意键显示下一屏。通过菜单选择按照工资卡号还是姓名浏览。如果按照卡号浏览,则显示的记录按照卡号升序输出;按照姓名浏览则按照字典序输出(调用排序模块的排序功能)。
(5)排序模块
排序模块提供菜单选择,实现按照工资卡号升序、实发工资降序以及姓名字典序排序。排序方法可以选择冒泡排序、插入排序、选择排序等。
(6)查询模块
实现按照工资卡号和姓名的查询,采用基本的查找方法即可。
(7)统计模块
输入起止月份,按照职工卡号和月份查询记录,把起止月份之间的实发工资金额累加。
题目很繁琐,代码也不是很难,直接上代码吧
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
int shuru = 0;//已经保存的数目
struct salary_info {
int Card_No; //工资卡号
char name[20]; //姓名
int month; //月份
double Init_Salary; //应发工资
double Water_Rate; //水费
double Electric_Rate; //电费
double tax; //税金
double Final_Salary; //实发工资
}SI[200];
double qtax(double m) {//求税金
double shui1 = 0, shui2 = 0;
if (m <= 800) {//低于800
return 0;
}
else if (m > 800 && m <= 1400) {//800-1400
return (m - 800) * 0.05;
}
else {//大于1400
return (m - 1400) * 0.1;
}
}
double qFinal_Salary(double a, double b, double c, double d) {//求实发工资
return a - b - c - d;
}
void menu();
void luru() {//录入信息
L1: int a = 0;//设置标记
double b = 0, c = 0, d = 0;
printf("请您输入您要建立的信息");//输入基本信息
printf("\n姓名:");
scanf_s("%s", SI[shuru].name);
printf("\n卡号 :");
scanf_s("%d", &a);
printf("\n月份:");
scanf_s("%d", &SI[shuru].month);
printf("\n应发工资:");
scanf_s("%lf", &b);
printf("\n水费:");
scanf_s("%lf", &c);
printf("\n电费:");
scanf_s("%lf", &d);
SI[shuru].Card_No = a;//赋值
SI[shuru].Init_Salary = b;
SI[shuru].Water_Rate = c;
SI[shuru].Electric_Rate = d;
SI[shuru].tax = qtax(b);
SI[shuru].Final_Salary = qFinal_Salary(b, c, d, qtax(b));
shuru++;//赋值完毕 数目+1
int f;
FILE* write=fopen("01.txt","ab");//写文件操作 ab追加操作
printf("1. 继续录入 2.返回主菜单");
scanf_s("%d", &f);
while (f == 1) {//继续录入
fwrite(&SI[shuru-1], sizeof(salary_info), 1, write);//把刚赋值的写入文件中
fclose(write);//关闭文件
goto L1;//到标记处运行
}
while (f == 2) {//写入文件
fwrite(&SI[shuru-1], sizeof(salary_info), 1, write);
fclose(write);
menu();
return;
}
}
void show() {//显示所有的信息
int i;
for ( i = 0; i < shuru; i++) {
printf("姓名:%s 卡号:%d 月份:%d 应发工资:%.2f 水费:%.2f 电费:%.2f 税金:%.2f 实发工资:%.2f\n", SI[i].name, SI[i].Card_No, SI[i].month, SI[i].Init_Salary, SI[i].Water_Rate, SI[i].Electric_Rate, SI[i].tax, SI[i].Final_Salary);
}
}
void read() {//读文件操作
FILE* read=fopen("01.txt","r");//指向文件 只读r
if (read == NULL) {//检测是否有文件
printf("无法读取文件\n");
return;
}
int rows = 0;// 定义一个文件行数记录变量
struct stat buf;// 定义一个buf结构体,用于得到文件内容
stat("01.txt", &buf);// 求文件中的行数(记录个数)
rows = buf.st_size / sizeof(salary_info);
while (!feof(read)) {//文件末的否
fread(SI, sizeof(salary_info), rows, read);// 读取数据到si中
}
shuru += (rows - 1);
fclose(read);
printf("读取成功\n");
}
void watch() {//浏览
int b = 0, i, j;
char asd;
struct salary_info x;//用具交换的中间值
while (b != 1 && b != 2) {
printf("1.姓名浏览 2.卡号浏览\n");//选择
scanf_s("%d", &b);
}
if (b == 1) {//姓名浏览
for (i = 0; i < shuru; i++) {//排序
for (j = i + 1; j < shuru; j++) {
if (strcmp(SI[i].name, SI[j].name) > 0) {
x = SI[j];
SI[j] = SI[i];
SI[i] = x;
}
}
}
for (i = 0; i < shuru; i++) {//交换完毕输出
printf("姓名:%s 卡号:%d 月份:%d 应发工资:%.2f 水费:%.2f 电费:%.2f 税金:%.2f 实发工资:%.2f\n", SI[i].name, SI[i].Card_No, SI[i].month, SI[i].Init_Salary, SI[i].Water_Rate, SI[i].Electric_Rate, SI[i].tax, SI[i].Final_Salary);
if (i % 9 == 0 && i > 0) {
printf("任意键下一页\n");
getchar();
getchar();
}
}
}
else if (b == 2) {//卡号浏览
for (i = 0; i < shuru; i++) {//按卡号排序
for (j = i + 1; j < shuru; j++) {
if (SI[i].Card_No>SI[j].Card_No) {
x = SI[j];
SI[j] = SI[i];
SI[i] = x;
}
}
}
for (i = 0; i < shuru; i++) {//排序完输出
printf("姓名:%s 卡号:%d 月份:%d 应发工资:%.2f 水费:%.2f 电费:%.2f 税金:%.2f 实发工资:%.2f\n", SI[i].name, SI[i].Card_No, SI[i].month, SI[i].Init_Salary, SI[i].Water_Rate, SI[i].Electric_Rate, SI[i].tax, SI[i].Final_Salary);
if (i % 9 == 0 && i>0) {
printf("任意键下一页\n");
getchar();//只输入而不操作
getchar();
}
}
}
}
void line() {//排序
int b = 0, i, j;
struct salary_info x;
while (b == 0) {
printf("1.卡号升序 2.工资降序 3.姓名排序\n");
scanf_s("%d", &b);
}
if (b == 1) {//卡号排序
for (i = 0; i < shuru; i++) {
for (j = i + 1; j < shuru; j++) {
if (SI[i].Card_No > SI[j].Card_No) {
x = SI[j];
SI[j] = SI[i];
SI[i] = x;
}
}
}
show();
}
else if (b == 2) {//工资降序
for (i = 0; i < shuru; i++) {
for (j = i + 1; j < shuru; j++) {
if (SI[i].Final_Salary < SI[j].Final_Salary) {
x = SI[j];
SI[j] = SI[i];
SI[i] = x;
}
}
}
show();
}
else if (b == 3) {//姓名排序
for (i = 0; i < shuru; i++) {
for (j = i + 1; j < shuru; j++) {
if (strcmp(SI[i].name, SI[j].name) > 0) {
x = SI[j];
SI[j] = SI[i];
SI[i] = x;
}
}
}
show();
}
}
void menu() {//菜单
printf("*************欢迎使用*************\n");
printf("*************菜单选择*************\n");
printf("************1.信息输入*************\n");
printf("************2.信息添加*************\n");
printf("************3.信息浏览*************\n");
printf("************4.信息排序*************\n");
printf("************5.信息查询*************\n");
printf("************6.信息统计*************\n");
printf("************0.显示菜单*************\n");
}
void find() {//查询操作
L: int i, f = 0, b = 0, d = 0;
printf("1.姓名查询 2.卡号查询\n");
scanf_s("%d", &b);
if (b==1) {//姓名查询
char c[20] = ""; printf("请输入姓名查询\n");
scanf_s("%s", c);//输入查询值
for ( i = 0; i < shuru; i++) {
if (strcmp(SI[i].name, c) == 0) {//找到并输出
printf("姓名:%s 卡号:%d 月份:%d 应发工资:%.2f 水费:%.2f 电费:%.2f 税金:%.2f 实发工资:%.2f\n", SI[i].name, SI[i].Card_No, SI[i].month, SI[i].Init_Salary, SI[i].Water_Rate, SI[i].Electric_Rate, SI[i].tax, SI[i].Final_Salary);
f++;//判断有没有找到的旗帜
}
}
if (f == 0) {
printf("没有您要查找的\n");
}
}
if (b == 2) {
printf("请输入您的卡号\n");
scanf_s("%d", &d);
for ( i = 0; i < shuru; i++) {
if (SI[i].Card_No == d) {//对比卡号
printf("姓名:%s 卡号:%d 月份:%d 应发工资:%.2f 水费:%.2f 电费:%.2f 税金:%.2f 实发工资:%.2f\n", SI[i].name, SI[i].Card_No, SI[i].month, SI[i].Init_Salary, SI[i].Water_Rate, SI[i].Electric_Rate, SI[i].tax, SI[i].Final_Salary);
f++;//判断有没有找到的旗帜
}
}
if (f == 0) {
printf("没有您要查找的\n");
}
}
printf("1.继续查询 2.返回主菜单\n");
scanf_s("%d", &b);
if (b == 1) {
goto L;//到标志
}
if (b == 2) {
menu();
}
}
void total() {//集合
int kaishi, jieshu;
double all[100] = { 0 };
printf("输入开始时间:");
scanf_s("%d", &kaishi);
printf("输入结束时间:");
scanf_s("%d", &jieshu);
int a[100] = { 0 }, b[100] = {0}, i = 0, j = 0, f = 0;
int ment;
for ( i = 0; i < shuru; i++) {//将卡号放入数组a中
a[i] = SI[i].Card_No;
printf("%d ",a[i]);
}
for ( i = 0; i < shuru; i++) {//将重复值变为-1
for (j = i+1; j < shuru; j++) {
if (a[i]==a[j]) {
a[j] = -1;
}
}
}
for ( i = 0,j=0; i < shuru; i++) {//去掉重复值的卡号
if (a[i]>=0) {
b[j] = a[i];
j++;
}
}
ment = j;//去除重复值的个数
for ( i = 0; i < j; i++) {
for (j = 0; j < shuru; j++) {//找相同卡号切月份在要求中的
if (SI[j].Card_No == b[i] && SI[j].month >= kaishi && SI[j].month <= jieshu) {
all[i] += SI[j].Final_Salary;
}
}
}
for ( i = 0; i < ment; i++) {//输出
printf("\n卡号:%d 统计工资:%lf",b[i],all[i]);
}
}
int main() {
int fl;
menu();
while (1) {
scanf_s("%d", &fl);
switch (fl) {
case 1:
read();
break;
case 2:
luru();
break;
case 3:
watch();
break;
case 4:
line();
break;
case 5:
find();
break;
case 6:
total();
break;
case 0:
menu();
break;
default:
return 0;
}
}
return 0;
}