实现医药公司定期对销售各药品的记录进行统计,可按药品的编号、单价、销售量或销售额做出排名。
功能要求:
(1)载入:从数据文件中读出各药品的信息记录,存储在顺序表中。各药品的信息包括:药品编号、药名、药品单价、销出数量、销售额。药品编号共 4位,采用字母和数字混合编号,如: A125,前一位为大写字母,后三位为数字
(2)排序:按药品编号进行排序时,可采用基数排序法。对各药品的单价、销售量或销售额进行排序时,可采用多种排序方法,对单价的排序采用冒泡排序法,对销售量的排序采用快速排序法,对销售额的排序采用堆排序法。
(3)输出:将各种排序结果输出显示。
#pragma once
#pragma warning(disable:4996)
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
//定义顺序表的存储结构;
typedef struct {
char numb[20]; //编号
char name[20]; //药名
float price; //单价
int amount; //销售量
float sumprice; //销售额
}RedType;
typedef struct {
RedType r[105]; //r[0]闲置或用作哨兵单元
int length; //顺序表表长
}SqList;
//读取文件
int readFile(SqList& L)
{
int i = 1;
FILE* file = fopen("medicines.txt", "r");
if (file == NULL)
{
printf("文件为空!\n");
return 0;
}
else { //通过fscanf输入 (指针,格式符,取地址)
while (fscanf(file, "%s %s %f %d %f",&L.r[i].numb, &L.r[i].name,
&L.r[i].price, &L.r[i].amount, &L.r[i].sumprice) != EOF)
//一直读到尾部,EOF作为文件结束的标志
{
i++;
}
L.length = i-1;
}
return 0;
}
//载入文件内容print
void load(SqList L)
{
printf("|药品编号\t|药名\t |药品单价\t|销售数量\t|销售额\t\n");
for (int i = 1; i <= L.length; i++)
printf("|%s\t\t|%s\t |%.2f \t|%d \t|%.2f \t\n",
L.r[i].numb, L.r[i].name, L.r[i].price, L.r[i].amount, L.r[i].sumprice);
printf("\n\n");
}
//基数排序-- 编号(numb)
void RadixSort(SqList& L)
{
//int min = 1, max = 1;
//for (int i = 1; i <= L.length; i++)
//{
// for (int j = 1; j <= L.length; j++)
// {
// if (strcmp(L.r[min].numb, L.r[j].numb) > 0)
// min = j;//找出本次循环最小的
// if (strcmp( L.r[j].numb,L.r[max].numb) > 0)
// max = j;
// }
// /*//选择排序
// if (min != i)
// {
// strcpy(L.r[0].numb, L.r[min].numb);
// strcpy(L.r[min].numb, L.r[i].numb);
// strcpy(L.r[i].numb, L.r[0].numb);
// }*/
//}
char *temp = (char*)malloc(sizeof(char));
//*printf("min:%d\n", min);
//printf("L.r[min].numb:%s\n", L.r[min].numb);
//printf("max:%d\n", max);
//printf("L.r[max].numb:%s\n", L.r[max].numb);*/
RedType bucket[10][10] = { 0 };
char dest[5] = { 0 };
int r=0;
int i, j, k;
int record[10][10] = { 0 }; //用于记录
int flag = 0;
int n = 5;
for (k = 3; k >= 0; k--)
{
for (i = 1; i <= L.length; i++)
{
j = 0;
strncpy(dest, L.r[i].numb + k, 1); //建字符串数组逐个取出
/*strcpy() 函数用来复制字符串;strncpy()用来复制字符串的前n个字符,所以要多传一个参数n
har *strcpy(char *dest, const char *src);
char * strncpy(char *dest, const char *src, size_t n);
不像strcpy(),strncpy()不会向dest追加结束标记'\0'*/
r = atoi(dest); //将字符串数字变成整型
/*atoi():int atoi(const char *str );
功能:把字符串转换成整型数。
str:要进行转换的字符串
返回值:每个函数返回 int 值,此值由将输入字符作为数字解析而生成。
如果该输入无法转换为该类型的值,则atoi的返回值为 0。
说明:当第一个字符不能识别为数字时,函数将停止读入输入字符串。*/
if(r==0)
{
if (n == 2) //取出字母的ASCII的个位
{
r = dest[0];
r %= 10;
}
if (n == 1) //取出字母的ASCII的十位
{
r = dest[0];
r /= 10;
}
}
while (record[r][j] != 0) //分别按照个、十、百位放进桶里
j++;
record[r][j] = 1;
strcpy(bucket[r][j].numb, L.r[i].numb);
bucket[r][j] = L.r[i];
}
int pos = 0;
for (i = 0; i < 10; i++)
for (j = 0; j <= L.length; j++)
if(record[i][j]==1) //将bucket里的数字(字符串)依次拿出
{
pos++;
L.r[pos] = bucket[i][j];
record[i][j] = 0;
bucket[i][j] = { 0 };
}
if (n > 0) //n为码位
{
n--;
if (n == 1)
k += 1;
}
}
load(L);
}
//堆排序--销售额(sumprice)
//是选择排序的一种,从逻辑上来理解成顺序存储的二叉树
void HeapAdjust(SqList& L, int k,int length)
{
L.r[0]= L.r[k];
L.r[0].sumprice = L.r[k].sumprice;
// 让i指向当前结点的左孩子
for (int i = 2 * k; i <=length; i *= 2) //沿着关键字较大的子节点向下筛选
{
if (i < length && L.r[i].sumprice > L.r[i + 1].sumprice) //取关键字较大的子节点的下标
i++;
if (L.r[i].sumprice >= L.r[0].sumprice) //筛选结束
break;
else {
L.r[k] = L.r[i]; //将L.r[i]这个较大的调整到双亲节点上
k = i; //修改k值,以便继续向下筛选
}
}
L.r[k] = L.r[0]; //被筛选结点的值被放入最终位置
}
void BuildMinHeap(SqList& L,int length) //建立小根堆
{
for (int k = length / 2; k > 0; k--) //从后往前调整所有非终端的节点
HeapAdjust(L, k,length);
}
void HeapSort(SqList& L)
{
int length = L.length;
BuildMinHeap(L,length);
for (int i = length; i > 1; i--)
{
L.r[0] = L.r[i];
L.r[i] = L.r[1];
L.r[1] = L.r[0];
HeapAdjust(L, 1, i - 1);
}
load(L);
}
//冒泡排序---单价(price)
//一次比较两个元素
void BubbleSort(SqList& L)
{
int i, j;
for (i = 1; i <= L.length ; i++) // 外层循环控制比较轮数
{
for (j = 1; j <= L.length - i; j++)// 内层循环控制每轮的比较次数
{
if (L.r[j].price < L.r[j + 1].price) // 如果前一个元素的价格小于后一个元素的价格
{
L.r[0] = L.r[j];
L.r[j] = L.r[j + 1];// 将后一个元素移到前一个位置
L.r[j + 1] = L.r[0];
}
}
}
load(L);
}
//快速排序---销售数量(amount)
int Patition(SqList& L, int low, int high)
{
//交换顺序表L中子表r[low..high]的记录,枢轴记录到位,并返回其所在位置
//此时在它之前(后)的记录均不大于(小于)它
L.r[0] = L.r[low]; //用子表的第一个记录作枢轴记录
int pivotkey = L.r[low].amount; //枢轴记录关键字
while (low < high) { //从表的两端向中间扫描
while (low < high && L.r[high].amount <= pivotkey)
--high;
L.r[low] = L.r[high]; //将比枢轴小的记录移动到低端
while (low < high && L.r[low].amount >= pivotkey)
++low;
L.r[high] = L.r[low]; //将比枢轴大的记录移动到高端
}
L.r[low] = L.r[0]; //枢轴记录到位
return low; //返回枢轴位置
}
void QSort(SqList& L, int low, int high)
{
//对顺序表L中的子序列L.r[low...high]做快速排序
if (low < high) { //长度大于等于1
int pivotloc = Patition(L, low, high); //一分为二
QSort(L, low, pivotloc - 1); //对低子表递归排序
QSort(L, pivotloc + 1, high); //对高子表递归排序
}
}
void QuickSort(SqList& L)
{
//对顺序表L做快速排序
QSort(L, 1, L.length);
load(L);
}
#include"medicines.h"
//主菜单
void menu()
{
printf("*************************************\n");
printf("**** 药店的药品销售统计系统 *********\n");
printf("*************************************\n");
printf("****\t1.载入文件内容\t*************\n");
printf("****\t各种排序:\t\t*****\n");
printf("****\t2.药品编号--基数排序\t*****\n");
printf("****\t3.药品单价--冒泡排序\t*****\n");
printf("****\t4.销售数量--快速排序\t*****\n");
printf("****\t5.销售额----堆排序\t*****\n");
printf("****\t0.退出\t\t*************\n");
printf("******* 请选择 **********************\n");
}
int main()
{
system("color F0\n");
menu();
SqList L;
readFile(L);
int n;
while (1)
{
scanf("%d", &n);
switch (n)
{
case 1://输入
//system("cls");
//menu();
printf("载入文件内容\n");
load(L);
break;
case 2://排序
//system("cls");
//menu();
printf("药品编号--基数排序\n");
printf(" 基数排序\n");
RadixSort(L);
break;
case 3:
//system("cls");
//menu();
printf("药品单价--冒泡排序\n");
printf(" 冒泡排序\n");
BubbleSort(L);
break;
case 4:
//system("cls");
//menu();
//printf("销售数量--快速排序\n");
printf(" 快速排序\n");
QuickSort(L);
break;
case 5:
//system("cls");
//menu();
printf(" 堆排序\n");
HeapSort(L);
//BuildMaxHeap(L);
break;
case 0:exit(0);//退出
break;
default:printf("无效,请重新输入!!\n");
}
}
return 0;
}