使用shell编写的魔幻盒子.docx
《使用shell编写的魔幻盒子.docx》由会员分享,可在线阅读,更多相关《使用shell编写的魔幻盒子.docx(14页珍藏版)》请在冰豆网上搜索。
![使用shell编写的魔幻盒子.docx](https://file1.bdocx.com/fileroot1/2023-1/25/58ea159f-2568-46cf-8292-63c989982549/58ea159f-2568-46cf-8292-63c9899825491.gif)
使用shell编写的魔幻盒子
《嵌入式操作系统》
实训报告
学号:
**********
姓名:
胜
题目:
魔幻盒子
*************
2011年12月28日
1、任务题目:
魔幻盒子
题目解释:
使用SHELL编程写一个能用ASCII码字符组成的长宽可变的四边形
2、性能、指标、要求:
2.1、基本要求
1)四边形绘图(40点*30点);
2)边的ASCII字符可以在按下某个按键的情况下可以修改;
3)四边形的四个角要求用不同的ASCII字符;
4)四边形的大小可变;
5)四边形的中间输出自己的与学号;
2.2、发挥部分
老师要求:
在按下某按键时能实现四边形的立体化
自我发挥:
1)学号的颜色会随着时间的变化不断变化
2)可以将方形变成圆形
3、方案设计
3.1、方案论证
3.1.1关于画平面四边形:
方案一:
由老师所给的“shell高级编程”文本中学习到的画盒子的方法,通过获得要画四边形的左上角坐标和要画四边形的长和宽来达到在终端上画四边形的目的。
方案二:
改编方案一的程序,将左上角的坐标固定,只需要长和宽就能在终端上画出四边形。
方案三:
自己通过实践想到的一个方法,获取当前终端大小,然后求出当前终端的中点位置,给出长和宽,以终端中点为中心画出一个四边形。
最终我决定使用方案三,前两种方案都可以画出盒子,但是在实现立体的时候容易超出终端,而第三种可以比较容易的定义一个条件来限制超出。
3.1.2关于画立体的斜边:
方案一:
直接使用最笨的方法,在要画斜边的角的位置,然后行减一、列加一,达到画出一条斜线的目的。
方案二:
使用勾股定理算出边的比例,然后通过比例确定坐标来画出斜边上的点。
这样就可以画出不同斜率的线。
而且可以自由设置斜边的长度。
我选择的是方案二,方案一虽然很简单,而且易懂,但是是投机取巧的,而且斜边的大小和斜边的斜率不可调。
这样对之后如果想进行图像变换也不容易,所以最终选择使用方案二
3.2、工作原理
3.2.1相关知识
3.2.1.1本次实训所使用的平台:
Linux操作系统
Linux简介:
Linux是一种自由和开放源码的类Unix操作系统。
目前存在着许多不同的Linux,但它们都使用了Linux核。
Linux可安装在各种计算机硬件设备中,从手机、平板电脑、路由器和视频游戏控制台,到台式计算机、大型机和超级计算机。
Linux是一个领先的操作系统,世界上运算最快的10台超级计算机运行的都是Linux操作系统。
严格来讲,Linux这个词本身只表示Linux核,但实际上人们已经习惯了用Linux来形容整个基于Linux核,并且使用GNU工程各种工具和数据库的操作系统。
Linux得名于计算机业余爱好者LinusTorvalds。
3.2.1.2本次实训使用的编程语言:
Shell
Shell是系统的用户界面,提供了用户与核进行交互操作的一种接口。
它接收用户输入的命令并把它送入核去执行。
实际上Shell是一个命令解释器,它解释由用户输入的命令并且把它们送到核。
不仅如此,Shell有自己的编程语言用于对命令的编辑,它允许用户编写由shell命令组成的程序。
Shell编程语言具有普通编程语言的很多特点,比如它也有循环结构和分支控制结构等,用这种编程语言编写的Shell程序与其他应用程序具有同样的效果。
3.2.1.3AWK
AWK是一种优良的文本处理工具。
它不仅是Linux中也是任何环境中现有的功能最强大的数据处理引擎之一。
这种编程及数据操作语言(其名称得自于它的创始人AlfredAho、PeterWeinberger和BrianKernighan姓氏的首个字母)的最大功能取决于一个人所拥有的知识。
AWK提供了极其强大的功能:
可以进行样式装入、流控制、数学运算符、进程控制语句甚至于置的变量和函数。
它具备了一个完整的语言所应具有的几乎所有精美特性。
实际上AWK的确拥有自己的语言:
AWK程序设计语言,三位创建者已将它正式定义为“样式扫描和处理语言”。
它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。
3.2.2程序中比较用的比较多的语句
echo:
shell中的输出,与C中的printf很类似。
本程序中用到的echo指令有很多种。
-e:
启用反斜线控制字符的转换(具体看下面)
-n:
取消行末换行
关于echo命令所支持的反斜线控制字符如下:
\a:
ALERT/BELL(从系统喇叭送出铃声)
\b:
BACKSPACE,也就是向左删除键
\c:
取消行末之换行符号
\E:
ESCAPE,跳脱键
\f:
FORMFEED,换页字符
\n:
NEWLINE,换行字符
\r:
RETURN,回车键
\t:
TAB,表格跳位键
\v:
VERTICALTAB,垂直表格跳位键
\\n:
ASCII八进位编码(以x开首为十六进制):
反斜线本身
echo–e“\E[a;bH”c的意思是在终端的第a行c列的位置输出c
echo–e“\E[am”的意思是前景色,其中a=30时为黑色,31时为红色,32绿色,。
。
。
40为黑色背景,31是红色背景,。
。
。
0为变回最初颜色
echo–e“\033[?
25l”是隐藏光标
echo–e“\033[?
25h”显示光标
read:
读取的命令
-s:
不在终端上打印输出的容
-n加数字:
代表键盘输入到多少位时自动读取,不用按回车
-t:
带上时间参数可以控制读取的时间,当达到指定的时间时自动停止读取
A=$(echo$a|awk‘{printf(“%d”,$1)}’)将a代入awk中运算,讲运算结果以整形输出到A。
tputlines:
获取当前终端的行数。
tputcols:
获取当前终端的列数。
tputcupxy:
将光标移动到x行y列处
sttyigncr:
忽略回车符
stty-igncr:
解除忽略回车符
clear:
清楚当前终端的容
exit:
退出
4、软件设计
主循环代码:
#main
echo-e"\033[?
25l"
W=30
H=20
Z="|"
Y="|"
S="-"
X="-"
C=0
colour1=0
draw_zhujiemian
sttyigncr
whiletrue
do
echo-e"\E[3${colour1}m"
draw_dot$[$MROW-1]$[$MCOL-5]"chensheng"
draw_dot$MROW$[$MCOL-5]"0952100111"
echo-e"\E[0m"
whileread-n1-t2a
do
if[$a=1]
then
clear
draw_box$W$H$Z$Y$S$X$C
echo-e"\E[3${colour1}m"
draw_dot$[$MROW-1]$[$MCOL-5]"chensheng"
draw_dot$MROW$[$MCOL-5]"0952100111"
echo-e"\E[0m"
stty-igncr
tputcup$[$ROW-3]0
read-p"High:
"h
read-p"Wide:
"w
H=$h
W=$w
sttyigncr
draw_zhujiemian
fi
if[$a=2]
then
colour_jiemian
whileread-n1-sb
do
if[$b=0]
then
colour_jiemian
fi
if[$b=1]
then
colour_jiemian
fi
if[$b=2]
then
colour_jiemian
fi
if[$b=3]
then
colour_jiemian
fi
if[$b=4]
then
draw_zhujiemian
break
fi
done
fi
if[$a=3]
then
clear
draw_box$W$H$Z$Y$S$X$C
echo-e"\E[3${colour1}m"
draw_dot$[$MROW-1]$[$MCOL-5]"chensheng"
draw_dot$MROW$[$MCOL-5]"0952100111"
echo-e"\E[0m"
tputcup$[$ROW-6]0
stty-igncr
read-p"Up:
"U
read-p"Down:
"D
read-p"Left:
"L
read-p"Right:
"R
sttyigncr
S=$U
X=$D
Z=$L
Y=$R
draw_zhujiemian
fi
if[$a=4]
then
clear
draw_box$W$H$Z$Y$S$X$C
echo-e"\E[3${colour1}m"
draw_dot$[$MROW-1]$[$MCOL-5]"chensheng"
draw_dot$MROW$[$MCOL-5]"0952100111"
echo-e"\E[0m"
a=1
b=1
x=10
A=$(echo$a$b$x|awk'{printf("%d\n",$1/sqrt($1*$1+$2*$2)*$3)}')
LRs=$[$Rs-$A]
LCz=$[$Cz+$A]
LCy=$[$Cy+$A]
echo-e"\E[3${C}m"
pd=1
for((c=$LCz;pd<=$[$W*2];c++))
do
draw_dot$LRs$c$S
letpd=pd+1
done
pd=1
for((r=$LRs;pd<=$H;r++))
do
draw_dot$r$LCy$Y
letpd=pd+1
done
pd=1
y1=$Cz
y2=$Cy
x1=$Rx
x2=$Rs
a=1
b=1
x=10
A=$(echo$a$b$x|awk'{printf("%d\n",$1/sqrt($1*$1+$2*$2)*$3)}')
for((i=0;i<=$A;i++))
do
B=$(echo$i$a$b|awk'{printf("%d\n",$1*$2/$3)}')
echo-e"\E[$[$x2-$B];$[$y1+$i]H""a"
echo-e"\E[$[$x2-$B];$[$y2+$i]H""b"
echo-e"\E[$[$x1-$B];$[$y2+$i]H""d"
done
tputcup$[$ROW-2]1
stty-igncr
echo-e"\E[0m"
read-s-p"PressENTERtoreturn!
"
draw_zhujiemian
sttyigncr
echo-e"\E[0m"
fi
if[$a=5]
then
clear
draw_boll$[$H/2]
echo-e"\E[3${colour1}m"
draw_dot$[$MROW-1]$[$MCOL-5]"chensheng"
draw_dot$MROW$[$MCOL-5]"0952100111"
echo-e"\E[0m"
stty-igncr
read-s
sttyigncr
draw_zhujiemian
fi
if[$a=0]
then
stty-igncr
clear
echo-e"\033[?
25h"
exit0
fi
done
letcolour1=colour1+1
if[$colour1=6]
then
colour1=0
fi
done
主循环流程图:
图1:
主流程图
画盒子的程序流程:
用了两个for循环来画出四条边,流程图如下:
具体程序:
echo"YouTerminalistoosmall!
"
stty-igncr
exit1
fi
if[$1-lt10]||[$2-lt3]
then
clear
echo"boxistoosmall"
stty-igncr
exit2
fi
MROW=$[$ROW/2]
MCOL=$[$COL/2]
Rs=$[$MROW-$2/2]
Cz=$[$MCOL-$1/2]
Rx=$[$Rs+$2-1]
Cy=$[$Cz+$1-1]
pd=1
echo-ne"\E[3${7}m"
for((r=$Rs;pd<=$2;r++))
do
draw_dot$r$Cz"$3"
draw_dot$r$Cy"$4"
letpd=pd+1
done
pd=1for((c=$Cz;pd<=$1;c++))
do
draw_dot$Rs$c"$5"
draw_dot$Rx$c"$6"
letpd=pd+1
done
在立体盒子的时候,用了勾股定理来求出三角形的三条边。
其中计算勾股定理的时候用了awk,利用awk进行浮点运算。
具体算法程序如下:
a=1
b=1
x=10
A=$(echo$a$b$x|awk'{printf("%d\n",$1/sqrt($1*$1+$2*$2)*$3)}')
B=$(echo$i$a$b|awk'{printf("%d\n",$1*$2/$3)}')
在画圆的程序中,利用了圆上的每个点到圆心的距离相等的定理,同样利用awk来计算其他两边的大小从而画出一个圆。
前期制作的时候,在主界面如果按下回车会出现错误,经过一番研究,从网上找到了屏蔽回车键的代码,sttyigncr,这样就解决了这个问题。
在主界面,光标老是会一直在闪,我就用了之前XX的echo的用法里面的一种,用echo–e“\033[?
25l”和echo–e“\033[?
25h”l来开启和关闭光标的闪烁。
5、制作与调试过程
5.1、摸索
实训刚开始,毫无头绪,shell本来以前就没接触过,上课也就稍微带了下,没有深入看过,于是开始认真看老师发下来的《shell高级编程》,通过上面的画盒子例程终于弄懂了一点原理,于是就开始做了。
一开始照着例程写完,运行,没效果。
经过一番分析,判定是终端过小,程序中有一判断当前终端能否画下一个盒子,终端过小就会退出。
调好终端,运行程序,成功画出了盒子,但是这个盒子是静态的,不能满足实训的可修改的要求,于是我分析了下完成这个程序需要的知识,然后一边开始认真的看老师发的《shell高级编程》,一边XX需要的功能要如何实现。
5.2、略懂
通过几天的研究,对于画盒子的程序基本都已经看懂了。
实际上就是利用for循环进行循环的行自加和列自加来达到在指定的行上画出两行,在指定的列上画出两列,拼在一起就是一个方形了。
而按下键盘控制方形大小,方形颜色,方形的边,其实就是利用read来循环读取键盘输入就可以完成了。
对于立体部分,其实我们只要在画出五条边,期中斜边最难了,要进行浮点运算,通过XX得知要使用awk来计算,研究了一个晚上awk,终于懂了点,可以进行计算了。
然后通过计算得出三角形的各边长度,进行画点就可以得到斜边了。
5.3、实践
有了一定的知识基础,可以认真从新开始本次实训了。
现在重新看实训的要求,发现有了新的见解。
于是我再次分析了下!
提出了三种方案,再一番分析,最终决定用方案三。
因为有了充分的学习和一些基础知识,很快就完成了程序。
程序完成,开始调试。
调试的时候我发现程序还是有漏洞的,就是边不能用*画出来。
用了很多种方法都无法解决这个问题,虽然现在解决不了,但是我相信通过今后的学习一定能找到解决的办法。
还有就是一开始的时候我用read–nx的写法来读取x个字符自动跳转,可是当我按下回车键就会出现异常字符,经过一番分析,发现可以用sttyigncr来屏蔽回车键来消除这个BUG。
还有就是光标老是会一闪一闪的,我就使用了echo–e“\033[?
25l”来取消光标闪烁。
最后的调试我只是优化了一下程序让程序运行的更完美。
6、实训心得体会
本次实训算是我们学校第一次嵌入式操作系统实训,以前的学长学姐们都没做过这个实训,没办法得到可参考的程序。
课堂上对于SHELL编程的介绍又不多,这次实训我们这种刚接触SHELL编程的菜鸟来说还是有一点难度的。
但是没有难点是无法克服的,老师提供了足够的自学资料和答疑指导,《shell高级编程》这本书让我对shell编程有了一定的认识,让我对shell编程有了一定的兴趣,网上也有很多相关的资料,也有专门研究此类编程的高手,这次实训为了寻找需要的信息,我也找了很多此类高手,认识了许多人。
对于如何从XX上获取更有用的信息我也有了一定的心得。
这次编程对我的编程思想也有了很大的提升,这个题目有点类似与点阵画图,我对于各种坐标的定位、光标的移动也有了一定的了解。
我们接下去准备做一些视频处理的研究,我相信经过这次的实训对我这些能力会有一定的提高。
学的越多就有越多东西想要了解,像后期的程序修改优化工作很多都是因为想要了解一些东西无意中发现了新的处理方法,比如像修改光标,屏蔽回车键之类方法的都是在无意中找到的。
本次实训结束了,但是我对于shell的学习不会停止,看的越多,越想了解其中的奥妙。
《Shell高级编程》这本书我感觉非常有用,很多本来自己解决不了的问题在看这本书部分都得到了解决,没解决的估计是还没看到吧。
这次能完成了这个实训,但是感觉还有很多不是非常了解,像AWK、正则表达式、管道的概念都还不是很清晰,以后还是会继续的学习下去。
这次实训还提高了我对于信息的收集能力,网络的上的资料非常多,如何能在众多的信息中找到相关的东西就要看信息的收集和处理能力了。
还有我了解到,学习东西一定要深入一点,而且要多实践,不然很多东西光靠看是不懂有什么用的,比如read的-s用法,光看字面的介绍都不懂什么意思,但是自己在代码中加上试了下,就知道这个是在输入的时候不在终端上打印出输入的字符。
这样的例子还有很多,实践出真知,我想这也是我们学校的实训想让我们明白的东西吧。