有一个员工文件salary_back.txt,salary_back.txt文件每行 为部门职员的姓名:工资(如tom:20000),题目要求:
- 求出该公司有多少人。
- 从工资文件salary_back.txt中读入全部工人,全部增加100元工资后并保存信息到文件salary.txt中。
- 将加工资之后的所有员工按工资进行降序排序,将排序后的结果选出工资最高TOP10在屏幕上输出。
【题目分析】
- 从文件salary_back.txt读取内容和写入salary.txt文件,都需要使用到文件操作。需要使用到fgets函数,一行一行的读取。
- 期间要对读取出来的数据进行分割,比如tom:20000要分割为tom和20000,这样才方便能处理。需要用到函数strtok。
- 分割出来得到的工资,要使用到atoi函数转换为int类型才能对数据进行加减操作。
- 读取出来的员工姓名和工资,我们需要有一个数据结构来储存他们,这里方法有很多,我们的代码中使用了结构体,并将每一个员工信息以链表的形式连接了起来。
- 最后要对数据进行排序和输出,所以涉及到链表的排序和打印等。
【程序代码】
#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; }