图书管理系统 C语言
前言
这是我学习C语言的第三个较正式的小项目,同样也是目前代码量和难度最大的一个挑战。这个图书管理的开发整体框架图如下,我自己凭借我能够想到的做了这么一个框架图,然后不断地去实现这些划分出来的模块。
思路分析
整个系统是由一个个小的功能模块组成的,我将其用思维导图的方式展现出来更有利于去实现这些功能模块。
图书管理系统由图书信息系统和借阅系统组成,图书信息系统是管理图书库存的,通过它实现图书的增加、删除以及像用户展示图书信息的功能,而借阅系统则是实现用户借书还书以及查询借书情况功能。
通过不断细分的模块去实现这些功能,一边写一边调试。
具体实现
-
首先,经过思考,把这些功能模块用函数表达出来,尽量思考的全面,先通过函数声明以及定义把它们放到框架里面,然后一个一个具体的去写相应的代码。
#define _CRT_SECURE_NO_WARNINGS //用于scanf警告 //头文件 #include<stdio.h> #include<string.h> //用于字符串比较 登陆系统以及查找信息 #include<stdlib.h> #include<windows.h> //背景色 屏幕清除 #include<conio.h> getch()函数 //宏定义 #define SIZE 20 #define ACCOUNT_PASSWORD "beipiao_707770" #define LEN sizeof(struct book) //分配内存 #define LEN1 sizeof(struct reader) #define ABC 'chaz'-'0' /*后面变量名太多 并且提示字符常量过多 用此表 */示 /* 结构体定义 */ //图书信息 struct book{ char name[SIZE]; //书名 char author[SIZE]; //作者 char publish[SIZE]; //出版社 int amount; //数量 float price; //单价 struct book* next; }; //借阅者信息 struct reader{ char rname[SIZE]; //姓名 char bname[SIZE]; //借阅书名 char date[SIZE]; //借阅时间 int rnum; //数量 struct reader* next; }; /* 函数声明 */ //初始化页面 void menu(); //选择系统 void SelectSystem(); //书籍数量 int NUM_BOOk(); //返回值为int类型 //借书人信息 int NUM_READER(); //返回值为int类型 //图书管理系统 void Library_System(); //新建图书信息 void New_Bulit(); //删除图书信息 void Delete(); //查询图书信息 void Inquire(); //浏览图书信息 (打印) void Browse(); //返回上一级 void Return(int i); //借阅系统 void Lending_System(); //借书 void Lending(); //还书 void Repay(); //查询借书情况】 void Show_Lending(); //查询信息 void Show_Look();
这里面有我自己最开始就已经想到的,也有后面增加的,有的函数所实现的功能与我预想的不符,但还是可以用。
2.具体实现 函数定义
- 通过函数来统计书籍的数量以及借阅者信息,返回值为int类型。为后面的循环提供条件。
/* 函数定义 */
//书籍数量信息
int NUM_BOOK()
{
FILE*fp;
int txcl=0,n;
float tprice =0;
char tname[SIZE]={'\0'},tauthor[SIZE]={'\0'},tpublish[SIZE]={'\0'};
fp=fopen("library.txt","r"); //以只读形式打开文件
for (n=0;!feof(fp);n++) //逐个打开文件
fscanf(fp,"%s%s%s%d%f",tname,tauthor,tpublish,&txcl,&tprice);
n--; //n初始赋值为0
fclose(fp); //关闭文件
return(n);
}
//借书人信息
int NUM_READER()
{
FILE*p;
int ID=0,n;
char lname[SIZE]={'\0'},ldate[SIZE]={'\0},lsname[SIZE]={'\0};
fp=fopen("reader.txt","r"); //以只读方式打开文件
for(n=0;!feof(fp);n++); //逐个打开文件
fscanf(fp,"%d%s%s%s ",&ID,&lname,&ldate,lsname);
n--; //n初始赋值为0
fclose (fp);
return (n);
}
这三个页面我写的很粗糙,还可以进行优化,返回上一级这个函数我开始是没有想到的,但最开始写到这里时才发现不返回上一级很难处理,所以就加了一个返回上一级的函数,同样也可以进行优化。思路都是一样的,通过按键或者输入数据进行判断,调用上一级函数。
账号登录这里我没有进行分开处理,分开处理需要加加两个储存账户和密码的文件,和借阅者信息文件一样的,输入错误这里也是,我并没有具体的去实现重新输入。我这个是1.0版本,不出意外的话以后会进行优化,学习其他的语言之后可能也会做一个类似的项目,虽然目前这个我觉得都不能称之为项目(哈哈) 。,。
这里开始用了system()进行了屏幕清除,后面也有用到,头文件为#include<windows.h>。
//返回上一级
void Return (int i)
{
switch (i) {
case 1: Library_System();
break;
case 2: Lending_System();
break;
}
}
//初始化页面
void menu()
{
int i;
char m[SIZE]; //账户及密码
printf("****************************************************\n");
printf("* 欢迎使用图书管理系统1.0 *\n");
printf("* 1. 登录系统 2. 退出系统 *\n");
printf("****************************************************\n");
printf("\n");
printf("请输:->");
scanf("%d", &i);
//登录
if (i == 1) {
int ret_1; //比较结果
//输入
printf("输入账户及密码:");
scanf("%s", m);
//s_gets(m, SIZE);
//判断是否正确
ret_1 = strcmp(m, ACCOUNT_PASSWORD);
if (ret_1 == 0)
{
printf("登录成功!\n");
system("cls");
//选择系统
SelectSystem();
}
}
//退出
else {
return;
}
}
//图书管理系统
void Library_System()
{
int i;
system("cls");
printf("****************************************************\n");
printf("* 1.新建 2.删除 3.查询 *\n");
printf("* 4.浏览 5.返回上一级 6.结束 *\n");
printf("****************************************************\n");
printf("\n");
printf("请输:->");
scanf("%d", &i);
switch (i)
{
case 1:New_Bulit();
break;
case 2:Delete();
break;
case 3:Inquire();
break;
case 4:Browse();
break;
case 5:Return(1);
break;
case 6:return 0;
break;
}
}
//借阅系统
void Lending_System()
{
int i;
printf("****************************************************\n");
printf("* 1.借书 2.还书 *\n");
printf("* 3.查询 4.浏览 *\n");
printf("* 5.返回上一级 6.结束 *\n");
printf("****************************************************\n");
printf("\n");
printf("请输:->");
scanf("%d", &i);
switch (i)
{
case 1:Lending();
break;
case 2:Repay();
break;
case 3:Inquire();
break;
case 4:Browse();
break;
case 5:Return(1);
break;
case 6:return 0;
break;
default:printf("输入有误,重新输入!\n");
break;
}
}
- 新建图书信息这些功能都涉及了文件和链表操作,文件的建立、读写,链表的增加、删除。
//新建图书信息
void New_Bulit()
{
FILE *fp;
char bname[SIZE]={'\0},bauthor[SIZE]={'\0'},bpublish[SIZE]={'\0'};
int bamount=0;
float bprice=0;
system("cls");
if((fp=fopen("library.txt","r"))==NULL) //打开文件
{
fp=fopen("library.txt","w");//以只写的形式打开文件,若不存在则新建
fclose(fp);
}
fp=fopen("library.txt","a"); //以追加的形式打开文件,若不存在则新建
printf("\n请按以下格式输入图书信息:\n 书名 作者 出版社 进库量 单价");
for (;i!=27;) //为了实现一次输入后按esc退出 这是我没有想到的
{
printf("请输入:\n");
scanf("%s%s%s%d%f",bname,bauthor,bpublish,&bamount,&bprice);
fprintf(fp,"%-9s%-14s%-16s%-7d%-.2f\n",bname,bauthor,bpublish,bamount,bprice);
printf("继续输入请按回车,结束请按Esc\n");
i=_getch(); //用getch 会有报错
for (;i!=13&&i!=27;) /*证只能是CR和Esc才能退出循环,输入其他字符无用,暂停程序,按‘CR’继续*/
i=_getch();
}
fclose(fp);
printf("操作成功,按任意键返回上一级!\n");
Library_System();
}
- 删除图书信息和新建图书类似,把删除后的链表覆盖到原有文件
//删除图书信息
void Delete()
{
struct book*head=NULL; //头结点
struct book*p,*p1,*p2;
int tamount =0,n=0,j,k;
float tprice=0;
char tname[SIZE]={'\0'},tauthor[SIZE]={'\0'},tpublish[SIZE]={'\0'},tnum[SIZE]={'\0'};
char dname[SIZE]={'\0'}; //删除书籍的名字
char i;
FILE *fp;
if((fp=fopen("library.txt","r"))==NULL) //打开文件,判断
{
system("cls");
printf("\n记录文件不存在,按任意键返回!"):
—getch();
Return (1);
}
else //实现删除功能
{
system ("cls");
printf("\n请输入要删除的书籍名字:");
scanf("%s",dname);
printf("\n确认删除请回车,取消请按Esc\n");
i=_getch();
for (;i!=13&&i!=27;)
i=_getch();
if(i=27) //取消
Return(1);
fp=fopen("library.txt","r");
j=NUM_BOOK();
for (k=0;k<j;k++)
{
fsanf(fp,"%s%s%s%d%f",tname,tauthor,tpublish,&tamount,&tprice);
if(strcmp(dname,tname)) //将不同名字的信息复制到链表
{
n++; //比较结果相同则n=0,不执行if,不同则执行
if(n==1) //建立链表
{
p1=p2=(struct book*)malloc(LEN);
head=p1;
}
else
{
p2->next=p1;
p2=p1;
p1=(struct book*)malloc(LEN); //新建链表
}
strcpy(p1->name,tname);//复制书名
strcpy(p1->author,tauthor);//复制作者名字
strcpy(p1->publish,tpublish); //复制出版社
p1->amount=tamount;//复制数量
p1->price=tprice; //复制单价
}
if(n==0) //图书只有一项且这一项刚好和要删除的相同
{
head=NULL;
}
else //建立链表的最后一个储存空间
{
p2->next=p1;
p1->next=NULL;
fclose(fp);
}
}
fp=fopen("library.txt","w");//清空文件,只写打开,然后关闭
fclose(fp);
fp=fopen("library.txt","a");//追加文件
p=head;
for(;p!=NULL;)//把链表内容覆盖到文件
{
fprintf(fp, "%-9s%-14s%-16s%-7d%-8.2f\n", p->name, p->author, p->publish, p->amount, p->price);
p = p->next;
}
fclose(fp);
system("cls");
printf("\n删除成功 \n按任意键返回上一层\n");
_getch();//返回上一层
Return(1);
}
}
- 查询相对而言简单,在文件中去查找匹配,根据结果输出
//查询图书信息
void Inquire()
{
FILE *fp;
int k=0,camount=0,m=0,n=0;
float price=0;
char cname[SIZE]={'\0'},cauthor[SIZE]={'\0'},cpublish[SIZE]={'\0'};
char i;
char target[SIZE]={'\0'};
if((fp=fopen("library.txt","r"))==NULL) //打开文件
{
system("cls");
printf("\n记录文件不存在,按任意键返回!");
_getch();
Return (1);
}
system("cls");
m=NUM_BOOK();
for(n=0;n<m;n++)
{
fscanf(fp,"%s%s%s%d%f",cname,cauthor,cpublish,&camount,&cprice);
if(!strcmp(target,cname)||!strcmp(target,cauthor))
{
if(k==0)
{
printf("查询结果:\n\n");
printf("书名\t\t作者\t\t出版社\t\t库存量\t单价\n");
}
printf("%-8s%-14s%-16s%-7d%-8.2f\n",cname,cauthor,cpublish,camount,cprice);
k++;
}
}
if(k==0) //文件夹为空则输出无记录并返回上一级
{
system("cls");
printf("\n无符合记录!\n");
_getch();
Return (1);
}
fclose(fp);//查询结束
_getch();
Return (1);
}
- 浏览图书则是把文件中的信息遍历之后打印出来
//浏览图书信息
void Browse()
{
FILE*fp;
int n=0;
int k=0,m=0,amount=0;
float price=0;
char name[SIZE]={'\0'},author[SIZE]={'\0'},publish[SIZE]={'\0'};
char i;
if((fp=fopen("library.txt","r"))==NULL)
{
system("cls");
printf("\n记录文件不存在,按任意键返回!");
_getch();
Return (1);
}
n=NUM_BOOK();
if(n==0)
{
system("cls");
printf("\n无任何记录!");
}
fp=fopen("library.txt","r");//打开只读文件
system("cls");
printf("\t书名\t作者\t出版社\t\t出版社\t\t库存量\t单价\n");
for(m=0;m<n;m++) //输出数据
{
fscanf(fp,"%s%s%s%d%f",name,author,publish,&amount,&price);
printf("%-14s%-16s%-18s%-7d%-8.2f\n", name, author, publish, amount, price);
}
fclose(fp);
printf("\n按任意键返回\n");
_getch();
Return (1);
}
- 借书 首先判断是否存在要借的书,再进行下一步记录借阅者信息操作 具体操作没太明白(copy了一段)
//借书
void Lending()
{
FILE*fp,*fp2;
struct book*head;
struct book*p,*p1,*p2;
int i,loop,k,n=0,flag=0,s=0;
int lnum = 0;
int lamount = 0;
float lprice=0;
char tname[SIZE]={'\0'},tauthor[SIZE]={'\0'},tpublish[SIZE]={'\0'},ttname[SIZE]={'\0'},rname[SIZE]={'\0'},date[SIZE]={'\0'},taname[SIZE]={'\0'};
system("cls");
if((fp=fopen("library.txt","r"))==NULL)
{
system("cls");
printf("\n图书馆无库存,按任意键退出!");
_getch();
exit(0);
}
else
{
printf("\n请输入借阅书名:\n请输入:");
scanf("%s",taname);
k=NUM_BOOK();
for(i=0;i<k;i++)//先将图书信息建立链表,更改库存
{
fscanf(fp,"%s%s%s%d%f",tname,tauthor,tpublish,&lamount,&price);
n++;
if(n==1)
{
p1=p2=(struct book*)malloc(LEN);
head=p1;
}
else
{
p2->next=p1;
p2=p1;
p1=(struct book*)malloc(LEN);
}
strcpy(p1->name, tname);//复制书名
strcpy(p1->author, tauthor);//复制作者
strcpy(p1->publish, tpublish);//复制出版社
p1->amount = lamount;//复制现存量
p1->price = tprice;//复制单价
}
if(n==0)
head=NULL;
else
{
p2->next=p1;
p1->next=NULL;
fclose(fp);
}
}
p=head;
for(;p!=NULL;)
{
if(!strcmp(p->name,taname))//判断要借的书是否存在
{
flag=1;
loop=p->amount;
(p->amount)--;
}
p=p->next;
if(flag&&(loop>0)) //存在被借图书并且库存大于0,把库存量变化后的链表存入文件
{
fp = fopen("library.txt", "w");
fclose(fp);
fp = fopen("library.txt", "a");
p = head;
for (; p != NULL;)
{
fprintf(fp, "%-9s%-14s%-16s%-7d%-8.2f\n", p->name, p->author, p->publish, p->amount, p->price);
p = p->next;
}
free(p);
fclose(fp);
if ((fp2 = fopen("reader.txt", "r")) == NULL)//建读者文件夹存入借书信息
{
fp2 = fopen("reader.txt", "w");//打开只读文件
fclose(fp2);
}
fp2 = fopen("reader.txt", "a");
printf("\n请按以下格式输入读者信息:\n 证号 姓名 借书日期 借书书名\n请输入:");//录入读者信息
scanf("%d %s %s %s", &lnum, rname, date, taname);
fprintf(fp2, "\n%-8d%-23s%-18s%-10s\n", lnum, rname, date, taname);
fclose(fp2);
printf("借书成功!请两个月内归还!!!按任意键返回\n");
_getch();//返回
Return(2);//调用借阅系统
}
}
}
- 还书 先确定还书者信息,与借阅者文件比较,存在则删去他的信息并且书籍库存量加一。
//还书
void Repay()
{
FILE*fp,*fp2;
strcut reader*head,*p1,*p2;
struct book*lhead1=NULL;
struct book*zp1,*lp1,*lp2;
int txcl=0,i;
float tprice=0;
char tname[20] = { '\0' }, tauthor[20] = { '\0' },
tpublish[20] = { '\0' }, ttname[20] = { '\0' };
int ttzhenghao = 0, tzhenghao = 0, n = 0, k = 0, t = 0, flag = 0;
char tmingzi[20] = { '\0' }, triqi[20] = { '\0' }, tzname[20] = { '\0' }, ttzname[20] = { '\0' };
char hitkey = 0;
system("cls");
{
if((fp=fopen("reafer.txt","r"))==NULL)//不存在借书人
{
system("cls");
printf("\n不存在借书人,按任意键退出!");
_getch();
system("cls");
Return (2);
}
else
{
{
printf("\n请输入读者证号和书名:\n请输入:");
scanf("%d %s", &ttzhenghao, ttzname);//输入还书证号和书名
k = NUM_READER();//获取读者文件夹信息个数
for (i = 0; i < k; i++)//读取读者文件夹信息
{
fscanf(fp, "%d%s%s%s\n ", &tzhenghao, tmingzi, triqi, tzname);
if ((ttzhenghao == tzhenghao) && !strcmp(ttzname, tzname))//如果证号书名存在,则标记为1
flag = 1;
}
fclose(fp);
fp = fopen("reader.txt", "r");//打开读者文件,删除借书信息
if (flag)
{
for (i = 0; i < k; i++)//将读者文件复制到链表
{
fscanf(fp, "%d%s%s%s\n ", &tzhenghao, tmingzi, triqi, tzname);//读取文件信息
if (!((ttzhenghao == tzhenghao) && !strcmp(ttzname, tzname)))
{
n++;
if (n == 1)
{
p1 = p2 = (struct reader*)malloc(LEN1);//新建链表
head = p1;
}
else
{
p2->next = p1;
p2 = p1;
p1 = (struct reader*)malloc(LEN1);//新建链表
}
p1->rnum = tzhenghao;//复制证号
strcpy(p1->rname, tmingzi);//复制读者名字
strcpy(p1->date, triqi);//复制日
strcpy(p1->bname, tzname);//复制书名
}
}
if (n == 0)
head = NULL;
else
{
p2->next = p1;
p1->next = NULL;
fclose(fp);
}
fp = fopen("reader.txt", "w");//清空读者文件
fclose(fp);
fp = fopen("reader.txt", "a");//追加信息
p = head;
for (; p != NULL;)//把链表内容覆盖读者文件
{
fprintf(fp, "\n%-8d%-23s%-18s%-10s\n", p->rnum, p->rname, p->date, p->bname);
p = p->next;
}
free(p);
fclose(fp);
}
}
}
}
if (flag)//标记为1,即还书时更改库存
{
{
{
printf("确认还书请按回车!");
for (; hitkey != 13 && hitkey != 27;)
hitkey = _getch();
if (hitkey == 13)
printf("成功!按任意键返回!");
n = 0; flag = 0;
fp3 = fopen("library.txt", "r");//打开图书馆文件
k = NUM_BOOK();//获取图书馆文件个数
for (i = 0; i < k; i++)//将图书馆文件复制到链表
{
fscanf(fp2, "%s%s%d%f",tname, tauthor, &txcl, &tprice);//读取信息
n++;
if (n == 1)
{
lp1 = lp2 = (struct book*)malloc(LEN);//新建链表
lhead1 = lp1;
}
else
{
lp2->next = lp1;
lp2 = lp1;
lp1 = (struct book*)malloc(LEN);//新建链表
}
strcpy(lp1->name, tname);//复制书名
strcpy(lp1->author, tauthor);//复制作者
strcpy(lp1->publish, tpublish);//复制出版社
lp1->amount = txcl; //复制现存量
lp1->price = tprice;//复制单价
}
if (n == 0)
{
lhead1 = NULL;
}
else
{
lp2->next = lp1;
lp1->next = NULL;
fclose(fp2);
}
}
}
zp1 = lhead1;
for (; zp1 != NULL;)
{
if (!(strcmp(zp1->name, ttzname)))//寻找书名相同
++(zp1->amount);//现存量加1
zp1 = zp1->next;
}
fp2 = fopen("library.txt", "w");//清空图书馆文件
fclose(fp);
fp2 = fopen("library.txt", "a");//追加信息
zp1 = lhead1;
for (; zp1 != NULL;)//把链表内容覆盖图书馆文件
{
fprintf(fp2, "-9s%-14s%-16s%-7d%-8.2f\n",
zp1->name, zp1->author, zp1->publish, zp1->amount, zp1->price);
zp1 = zp1->next;
}
fclose(fp2);
_getch();//返回
Return(2);//调用借阅系统
}
else
printf("不存在此信息!按任意键返回!");
_getch();//返回
Return(2);//调用借阅系统
}
- 查询借书情况,把所有的借书信息打印出来
//查询借书情况
void Show_Lending()
{
FILE*fp;
int ID=0,xcl=0,n=0,i=0,j=0;
char name[SIZE]={'\0'},date[SIZE]={'\0'},bname[SIZE]={'\0'};
if((fp=fopen("reader.txt"."r"))==NULL)//打开只读文件
{
system("cls");
printf("\n记录文件不存在,按任意键返回!");
_getch();
Return(2);
}
n==NUM_BOOK();
if(n==0)
{
system("cls");
printf("\na无任何记录!");
}
fp=fopen("reader.txt","r");
system("cls");
printf("\n证号\t读者姓名\t\t借书日期\t书名\n");
for(;!feof(fp);)//输出信息 foef()是在文件已经打开的基础上用于验证文件是否读取结束
{
fscanf(fp,"%d%s%s%s\n",&ID,name,date,bname);
printf("\n%-8d%-23s%-18s%-10s\n",ID,name,date,bname);
}
fclose(fp);
printf("\n按任意键返回!\n");
_getch();
Return(2);
}
- 查询一个人的借书情况, 输入要查找的证件号或者姓名到借阅者文件里面匹配,输出相应的结果。
//查询信息
void Show_Look()
{
FILE*fp;
int num=0,k=0,amount=0,m=0,n=0;
char ID[SIZE]={'\0'},date[SIZE]={'\0'},bname[SIZE]={'\0'};
char i=0;
char target[size]={'\0'};
if((fp=fopen("reader.txt","r"))==NULL)//打开只读文件
{
system("cls");
printf("\n记录文件不存在,按任意键返回!");
_getch();
Return (2);
}
system("cls");
printf("请输入证件号或者姓名查询:\n");
scanf("%s",target);
system("cls");
n=NUM_BOOK();
for(n=0;n<m;n++)
{
fscanf(fp,"%d%s%s%s",&num,name,date,bname);
if(!strcmp(target,name)||(ABC)==num)
{
if(k==0)
{
printf("查询结果:\n\n");
printf("\n证号\t读者姓名\t\t借书日期\t书名\n");
}
printf("\n%-8%-23s%-18s%-10s\n",ID,name,date,bname);
k++;
}
}
if(k==0) //文件夹为空则输出无记录并返回上一级
{
system("cls");
printf("\n无符合记录\n");
_getch();
Return(2);
}
fcose(fp);
_getch();
Return(2);
}
总结
-
通过这个小项目的练手,主要总结出了两方面的问题。
-
首先,我在准备的过程中,思考不足,很多地方没有想到,比如返回上一级这个功能。结果可想而知,在动手敲代码的时候总会有很多临时需求冒出来,很是痛苦。并且在准备的过程中我并没有很强的逻辑性,所以在后面写文档的时候需要重新整理思路,当然,在这个过程中我也收获了许多。在准备的时候我选择用思维导图的方式,我初步学习了如何制作思维导图,更加熟悉小工具的使用。准备周期长但准备效果并没有达到预期。
其次,就是在敲代码的过程中出现的问题。 万事开头难,这一次并没有出现明显开头难的问题,我对比上一次这次明显有进步,我自己先把大致的框架写了出来,然后具体去实现。初生牛犊不怕虎,很明显。然后就出现了问题,开始解决问题,有的问题还没有解决掉,可能是我自己经验知识点还不够,所以这些问题我会过一段时间再回过头来解决。有一个问题感觉很初级,就是变量命名,虽然这次涉及的变量命名不是很多,但我还是在命名上出现了问题,命名没有弄好的那注释就很重要(虽然注释本来就很重要),不然过段时间自己都不知道这些变量是什么意思。每次解决问题的过程就是提升自己的过程,这一次我已经有了不错的收获。
下面是我的一些自我鼓励吧,也是心中的一些想法。
每当自己心里有一个想法的时候,我们要尽可能地去实现它,学编程真的得多敲代码,有时候在实际行动中会出现许多以前自己没有遇到过的问题,而解决这些问题就是提升自己的有效途径,这与学习书本知识是不一样的,而这也是我认为编程的魅力之处,虽然这个过程很痛苦,但痛并快乐着。
实践是检验真理的唯一标准,学习就得不断实践。每天坚持学习,哪怕每天进步一点点我们也会不断靠近我们的目标,制定好每天的计划然后努力完成,坚持下去,会有许多收获的,虽然可能别人无法理解,但我们自己要坚定我们所热爱的,朝着目标前进。可能是自学的原因,也有其他方面的影响,遇到很难的问题的时候我也会逃避, 但最后还是会花时间去解决,尽管问题有时候还是不能解决,但这很正常,我们过段时间后可能新学到的知识会让我们理解之前的一些问题。学习没有捷径可走,我相信笨鸟先飞、勤能补拙,我自己是不会轻易放弃的,总得去试一试,哪怕结果不如人意,但我还是想去看看风景,哈哈哈。