有一个员工文件salary_back.txt,salary_back.txt文件每行 为部门职员的姓名:工资(如tom:20000),题目要求:

  1. 求出该公司有多少人。

  2. 从工资文件salary_back.txt中读入全部工人,全部增加100元工资后并保存信息到文件salary.txt中。

  3. 将加工资之后的所有员工按工资进行降序排序,将排序后的结果选出工资最高TOP10在屏幕上输出。

    【题目分析】

  4. 从文件salary_back.txt读取内容和写入salary.txt文件,都需要使用到文件操作。需要使用到fgets函数,一行一行的读取。

  5. 期间要对读取出来的数据进行分割,比如tom:20000要分割为tom和20000,这样才方便能处理。需要用到函数strtok。

  6. 分割出来得到的工资,要使用到atoi函数转换为int类型才能对数据进行加减操作。

  7. 读取出来的员工姓名和工资,我们需要有一个数据结构来储存他们,这里方法有很多,我们的代码中使用了结构体,并将每一个员工信息以链表的形式连接了起来。

  8. 最后要对数据进行排序和输出,所以涉及到链表的排序和打印等。

【程序代码】

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
// 链表结构体
typedef struct emp
{
char *name;
int sal;
struct emp *next;
}Emp;
 
// 获取总人数
int getCount(char* szFileName);
// 创建链表
Emp* createList();
// 读取所有人到链表中
int readFileToList(Emp* head, char* srcFile);
// 打印链表所有数据
void displayList(Emp* head);
// 计算节点个数
int getListLen(Emp* head);
// 排序
void sortList(Emp* head, int len);
// 输出前10个有效数据
void showTopTen(Emp* head);
// 保存到新文件
int saveToFile(Emp* head, char* destFile);
// 销毁链表
void destoryList(Emp* head);
 
int main(int argc, char* argv[])
{
int nCount = 0;
nCount = getCount(“salary_back.txt”);
printf(“公司内一共 %d 个人\n”, nCount);
 
// 创建链表
Emp* head =createList();
// 读取数据存放到链表
readFileToList(head, “salary_back.txt”);
// 打印一次数据
// displayList(head);
// 计算有效节点个数
int nLen = 0;
nLen = getListLen(head);
// 排序
sortList(head, nLen);
// 打印一次数据
// displayList(head);
// 打印Top10
showTopTen(head);
// 保存到文件
saveToFile(head, “salary.txt”);
// 销毁链表
destoryList(head);
 
system(“pause”);
return 0;
}
 
void destoryList(Emp* head)
{
Emp* tmp = head;
while (head)
{
head = head->next;
free(tmp);
tmp = head;
}
}
 
int saveToFile(Emp* head, char* destFile)
{
FILE *pFile = fopen(destFile, “w+”);
if (NULL == pFile) return -1;
 
head = head->next;
char buf[256] = {0};
char ch[128];
while (head)
{
// 把链表中的内容拼接起来
strcat(buf, head->name);
strcat(buf, “:”);
strcat(buf, _itoa(head->sal, ch, 10));
// 添加\n
buf[strlen(buf)] = ‘\n’;
fwrite(buf, strlen(buf), 1, pFile);
 
memset(buf, 0, sizeof(buf));
head = head->next;
}
 
fclose(pFile);
}
 
void showTopTen(Emp* head)
{
int n = 10;
head = head->next;
 
printf(“Top 10\n”);
 
while (head && n–)
{
printf(“%s — %d\n”, head->name, head->sal);
head = head->next;
}
}
 
void sortList(Emp* head, int len)
{
Emp* p;
Emp* q;
Emp* pre;
Emp* tmp;
for (int i = 0; i < len - 1; i++)
{
// pre一直跟随着是p节点的上一个节点
pre = head;
// p一直是pre的下一个节点
p = pre->next;
// q一直是p的下一个节点
q = p->next;
for (int j = 0; j < len - 1 - i; j++)
{
// 判断p的data是否大于q的data
if (p->sal < q->sal)
{
// 让pre的next等于q的当前位置
pre->next = q;
// 让p的next指向q的next
p->next = q->next;
// 让q的next指向p,至此指针交换完毕
q->next = p;
 
// 如果要继续下次循环,必须恢复p和q的位置为进入循环前保持的位置
tmp = p;
p = q;
q = tmp;
}
// 所有指针向后移动一次
pre = p;
p = q;
q = q->next;
}
}
}
 
int getListLen(Emp* head)
{
int nCount = 0;
head = head->next;
while (head)
{
nCount++;
head = head->next;
}
return nCount;
}
 
void displayList(Emp* head)
{
head = head->next;
while (head)
{
printf(“%s – %d\n”, head->name, head->sal);
head = head->next;
}
}
 
Emp* createList()
{
Emp* head = (Emp*)malloc(sizeof(Emp));
head->next = NULL;
return head;
}
 
int readFileToList(Emp* head, char* srcFile)
{
FILE* pFile = fopen(srcFile, “r”);
if (NULL == pFile) return -1;
 
char buf[256];
Emp* cur = NULL;
while (fgets(buf, 256, pFile))
{
// 判断读取的行内是否有有效数据
if (strlen(buf) > 1)
{
// 把\n换成\0
//if (buf[strlen(buf) - 1] == ‘\n’)
// buf[strlen(buf) - 1] = ‘\0’;
 
cur = (Emp*)malloc(sizeof(Emp));
 
char* pPos = NULL;
// 人名
pPos = strtok(buf, “:”);
// 将名字放入节点中name成员
cur->name = (char*)malloc(strlen(pPos) + 1);
strcpy(cur->name, pPos);
 
// 工资
pPos = strtok(NULL, “:”);
// 将工资放入节点中sal成员
cur->sal = atoi(pPos) + 100;
 
// 将新加点插入链表(头插法)
cur->next = head->next;
head->next = cur;
}
}
 
fclose(pFile);
}
 
int getCount(char* szFileName)
{
int nCount = 0;
FILE *pFile = fopen(szFileName, “r”);
if (NULL == pFile) return -1;
 
char buf[256];
while (fgets(buf, 256, pFile) != NULL)
{
// 确定读取的每行数据中超过2个有效字符,如果只有1个那证明是个空行
if (strlen(buf) > 1) nCount++;
//printf(“%d “, strlen(buf));
}
 
fclose(pFile);
return nCount;
}