设计目标
利用文件IO 与 数据结构 制作一个 超市购物系统
功能描述:
1.程序运行检索目录下图片信息 利用文件IO写入读取商品信息保存到链表中
2.点击饮料/零食位置 显示饮料/零食界面 根据用户选择商品 自动跳到商品详细界面,能够实现上一张下一张播放商品信息,能够加入购物车并自动添加到购物车链表中,支持直接购买商品。
3.点击购物车位置,自动遍历购物车的商品,能够实现商品数量的增加和删除,删除直到数量为0时,自动把该商品剔除。购物车同时能够分页显示。
4.结算功能:点击结算功能自动结算购物车里所有的商品价格,并且屏幕刷一张图显示出来。
代码编写过程:
设计方案:
通过文件IO 读取文件信息存储到链表中,实现链表的增删改查数据功能,通过触摸屏和jpg显示,字库操作 来设计完善项目。
系统框架:
实现过程:
1.把商品的 价格 数量 名称 图片路径 存放到一个文件中
2.程序启动 加载 商品文件 中的信息 到 数据结构中。
3.遍历数据结构,把图标 和商品其他信息 利用字库显示到
LCD 设备中。
4.根据用户点击的位置,确定选择了哪项功能,点击 饮料
或 零食。重新遍历数据结构显示。 根据用户点击的商品位置添加到 购物车链表中。
5.点击购物车,遍历购物车链表 显示购物车中的所有内容
主函数:
主函数主要初始化头结点 读取文件的链表信息存入
int main(int argc, char const *argv[])
{
//初始化设备
init_all();
//1.清屏 设置为黑色
set_black();
read_JPEG_file("./img/state_drink.jpg",0,435);
//新建饮料头结点
struct D_node *head = Create_Node(0,"","");
//新建零食头结点
struct D_node *snack_head = Create_Node(0,"","");
//创建购物车链表头结点
struct D_node *shop_head = Create_Node(0,"","");
read_node(head,"shop_drink.txt");
read_node(snack_head,"shop_snack.txt");
// find_image(argv[1],head);
// find_image(argv[1],shop_head);
//printf("检索完毕!\n");
//write_node(head,"shop_drink.txt");
// write_node(shop_head,"shop_snack.txt");
// Traver_Nodes(snack_head);
Traver_Nodes(head);
//主界面运行函数
screen_control(head,snack_head,shop_head);
return 0;
}
界面设计:
先说饮料界面和零食界面吧:
先刷一张饮料界面的图,
//1.清屏 设置为黑色
set_black();
read_JPEG_file("./img/state_drink.jpg",0,435);
通过文件IO遍历文本存储的链表节点数据到链表中,
//读取文件中的链表数据 需要第一个节点的地址
void read_node(struct D_node *head,char *pathname)
{
FILE * fp = fopen(pathname, "r");
if(fp == NULL)
{
printf("打开文件失败\n");
return ;
}else
{
printf("打开文件成功\n");
}
//这里是读取第一个节点为头结点 并初始化
int size = fread(head,sizeof(struct D_node),1,fp);
head->prev = head;
head->next = head;
while (1)
{
struct D_node read_node ;
size = fread(&read_node,sizeof(struct D_node),1,fp);
printf("size:%d\n",size);
//判断读取数据为空 跳出循环
if(size == 0)
break;
printf("商品: %s 价格:%.2f 路径:%s\n",read_node.name,read_node.money,read_node.pathname);
//尾插入数据
Insert_Node(head,read_node.money,read_node.name,read_node.pathname);
}
printf("链表结点读取保存成功========================\n");
fclose(fp);
}
主利用双向循环链表来遍历数据中的图片 计算相互之间的间隔 通过jpg格式刷新出来
void Traver_Nodes(struct D_node *head)
{
struct D_node *pos = head->next;
int i = 0 , j = 0;
while (1)
{
printf("商品名:%s 价格:%.2f图片路径:%s\n",pos->name, pos->money,pos->pathname);
//显示文字
//4.将字体写到点阵图上
char buf[512] = {0};
sprintf(buf,"%s 价格:%.2f元",pos->name,pos->money);
bitmap *bm = createBitmapWithInit(120,30,4,getColor(0,192,128,0));
fontPrint(f,bm,2,2,buf,getColor(0,0,0,0),0);
//5.把字体框输出到LCD屏幕上
if(i <= 5)
{
show_font_to_lcd((int *)lcd,130*i,180,bm);
read_JPEG_file(pos->pathname,130*i,0);//4*130 520 5*130 650 6*130 780
i++;
}else if(j <= 5)//换行遍历
{
show_font_to_lcd((int *)lcd,130*j,400,bm);
read_JPEG_file(pos->pathname,130*j,220);//4*130 520 5*130 650 6*130 780
j++;
}
pos=pos->next;
if(pos == head)
break;
}
printf("========================\n");
}
商品详细查看:
主函数设置4个标志 分别为饮料界面标志 零食界面标志 购物车界面标志 商品详细界面标志 1 2 3 4
使用触摸屏判断xy点击的是第几个节点的商品
int x = 0,y = 0, location = 0;
int buy_flag = -1;
get_xy(ts_fd,&x,&y);
location = return_position(x,y);
printf("location:%d\n", location);
if(location != 0)
{
flag = 4;
information_pag_display(head,shop_head,location);
}
传入显示界面 通过节点的pos=pos->next 和pos = pos->prev 实现图片上一张下一张播放。加入购物车 购买商品
//商品详细界面 获取商品信息,左右查看商品,购买或者返回菜单
int information_pag_display(struct D_node *head,struct D_node *shop_head ,int n)
{
read_JPEG_file("./img/information_page.jpg",0,0);
struct D_node *tmp = Find_Node(head,n,shop_head);
read_JPEG_file(tmp->pathname,330,126);
show_shop_price_name(tmp);
while(1)
{
int x = 0,y = 0;
get_xy(ts_fd,&x,&y);
printf("x=%d y=%d\n",x,y);
if(y>394 &&y<480 && x>0 &&x<166)//退出返回主菜单
{
//1.清屏 设置为黑色
set_black();
read_JPEG_file("./img/state_drink.jpg",0,433);
Traver_Nodes(head);
flag = 1;
break;
}
if(y>396 &&y<480 && x>298 &&x<503)//购买商品后3秒自动返回
{
read_JPEG_file("./img/buysuccess.jpg",0,0);
show_shop_price_name(tmp);
sleep(2);
set_black();
read_JPEG_file("./img/state_drink.jpg",0,435);
Traver_Nodes(head);
flag = 1;
break;
}
if( y>137 &&y<227 && x>565 &&x<800)//显示下个商品以及数量
{
if(tmp->next==head)
{
tmp=tmp->next;
}
tmp=tmp->next;
read_JPEG_file(tmp->pathname,330,126);
show_shop_price_name(tmp);
}
if( y>120 &&y<220 && x>0 &&x<230)//显示上个商品以及数量
{
if(tmp->prev==head)
{
tmp=tmp->prev;
}
tmp=tmp->prev;
read_JPEG_file(tmp->pathname,330,126);
show_shop_price_name(tmp);
}
if(y>400 &&y<480 &&x>620 &&x<800)//购物车
{
printf("加入购物车\n");
struct D_node *pos = judge_node_repeat(shop_head,tmp);
//判断是否重复
if(pos!=NULL)
{
pos->sum++;
}
else
{
Insert_Shop_Node(shop_head,tmp->money,tmp->name,tmp->pathname,1);
}
read_JPEG_file("./img/add_shopsucess.jpg",0,0);//显示加入购物车成功图片
read_JPEG_file(tmp->pathname,330,126); //显示商品图片
sleep(1);
read_JPEG_file("./img/information_page.jpg",0,0);//显示主界面图片
read_JPEG_file(tmp->pathname,330,126);
show_shop_price_name(tmp);
}
}
return 1;
}
购物车功能:
购买商品:
if( x >700 && x< 800 && y>339 && y<439 )
{
//付款结算
float price = goods_payment(shop_head);
printf("需要付款的金额为:%.2f\n",price);
//刷新界面
read_JPEG_file("./img/payallsuccess.jpg",0,0);
//将字体写到点阵图上
char buf[512] = {0};
font *f1 = fontLoad("/usr/share/fonts/DroidSansFallback.ttf");
sprintf(buf,"金额:%.2f元",price);
bitmap *bm = createBitmapWithInit(200,45,4,getColor(0,200,214,223));
fontSetSize(f1,45);
fontPrint(f1,bm,2,2,buf,getColor(0,0,0,0),0);
//5.把字体框输出到LCD屏幕上
show_font_to_lcd((int *)lcd,214,112,bm);
sleep(1);
//删除购物车所有节点
delete_shopping_cart_all_nodes(shop_head);
//返回主界面
flag = 1;
set_black();
read_JPEG_file("./img/state_drink.jpg",0,433);
Traver_Nodes(head);
}
购物车的上一页下一页:
if(x >695 && x< 800 && y>190 && y<270)//下一页
{
//刷新界面
read_JPEG_file("./img/shopping_cart1.jpg",0,0);
//遍历显示
Traver_Shoppag2_Nodes(shop_head);
second_page_logo = 1;
}
if(x>0 && x<155 && y>0 && y<70)//点击返回第一页
{
//刷新界面
read_JPEG_file("./img/shopping_cart.jpg",0,0);
//遍历显示
Traver_Shop_Nodes(shop_head);
second_page_logo = 0;
}
因为这里涉及到数据的增加和删除 需要标志位来使第一页或者第二页的数据操作限制,
location = return_shoplist_position(x,y);
buy_flag = return_buy_flag(x,y);//这里标志0 1 表示是删除还是增加
printf("x:%d y:% location:%d buy_flag:%d second_page_logo:%d\n",x,y,location,buy_flag,second_page_logo);
if(buy_flag != -1)
{
if(second_page_logo)
{
Update_Shop_Node(shop_head,buy_flag,location+4);
}else{
Update_Shop_Node(shop_head,buy_flag,location);
}
}
数据更新函数:
//查询购物车第几个节点的数据 并更新数据 需要传入第几个节点
int Update_Shop_Node(struct D_node *shop_head,int set_flag, int n)
{
struct D_node *pos = shop_head->next;//定义pos指针遍历
int i = 1;
while (pos != shop_head)
{
if(i == n)
{
printf("找到啦!商品: %s 价格:%.2f数量:%d\n",pos->name,pos->money,pos->sum);
//更新节点 判断是增还是减
if(set_flag == 1)
{
//增加
pos->sum++;
}else{
//减少
pos->sum--;
if(pos->sum == 0)
{
//删除节点
Remove_Node(shop_head,pos->name);
//Traver_Shoppag2_Nodes(shop_head);
break;
}
}
}
pos=pos->next;
i++;
}
if(second_page_logo==0)//购物车分页标志 第一页
{
set_black();
read_JPEG_file("./img/shopping_cart.jpg",0,0);
Traver_Shop_Nodes(shop_head);
}else
{
set_black();
read_JPEG_file("./img/shopping_cart1.jpg",0,0);
Traver_Shoppag2_Nodes(shop_head);
}
return 0;
}
界面设计比较简陋勿喷哈哈~大体功能实现演示讲解到此!谢谢观看
心得体会:
此次项目主要花的时间在于判断x y坐标 判断图片显示的位置 这里比较繁琐 其他功能实现主要是数据结构的双链表知识,通过这次项目 ,更加深刻的吸收链表文件IO知识!