day 4

复习:

什么是shell脚本

批处理linux命令的脚本语言

什么脚本 语言?是解释型语言,有解析器来阅读脚本代码。

预设变量

$0 $1$2 $3 $4… $#数量 $*参数的集合 运行脚本文件的时候在命令中添加参数

变量

变量无需定义,可以直接使用,变量名尽量大写, 读取变量的值 $变量名

输入

read -p “qhewhqwkjehklqw” 变量

输出

echo ""不完全输出 可以加入变量的值 ''完全输出 无法使用变量

运算

+ - \* 或者 '*'  / %
`expr $NUM1 + $NUM2`

字符串判断

=判断字符串相等

-z判断字符串为空

数值判断

-eq 相等

-ne 不相等

-gt 大于

-ge 大于等于

-lt 小于

-le 小于等于

文件类型

-f 普通文件

-d 目录文件

-e 存在

-L 链接文件

-w 写权限

-x 可执行权限

case结构

case $(变量) in

a)

​ 语句。

​ ;;

​ b)

​ 语句。

​ ;;

​ *) # 相当于C语言的default

​ ;;

esac

作业:

  1. 下面的代码执行后a的值为( 2 )

int a = 10;

if(a = 1) //因为是=运算,所以表达式的结果是=左值,左值是1,所以if条件为真

{

a++;

}

else

{

a--;

}

printf("%d", a);

2 下面的代码a的值是( 10 )

int a = 10;

if(a < 10)

{

a++;

}

  1. ‘3’ 的Ascii码用16进制表示是( 0x33 ) 10进制是( 51 )。

4 . int main()

{

int a;

scanf("%d", &a);

switch(a) 

{

case 1:

	printf("Monday\n");

case 2:

	printf("Tuesday\n");

case 3:

	printf("Wednesday\n");

default:

	printf("Error\n");

}

}

如果用户输入了2, 那么输出是( )

Tuesday

Wednesday

Error

  1. 如果int a = 3, 输出003,那么输出表达式为( printf("%03d", a); )

    %d 整数

    %nd 输出n位,如果n大于整数的位数,左边补空格,如果n小于整数的位数,完整输出整数。

    比如整数123 %5d输出 空格空格123

    比如整数123 %2d输出 123

    %0nd 输出n位,如果n大于整数的位数,左边补0,如果n小于整数的位数,完整输出整数。

    n左边的数字如果要写只能是0

6 .下面的语句有什么错误

int main()

{

int a;

scanf("%d", a);   //1 &a   

printf("%f", a);  //2 %d

return 0;

}

  1. float money = 12.1, 如果输出的金额保留小数点两位,则输出表达是为( printf("%.2f", money); )

%nf 输出n位

%n.mf 输出n位,小数点后m位

%.mf 不在乎输出位数,只要小数点后m位

  1. int main()

{

int i = 0, sum = 0;

for(i = 0; i < 100; i++)
{
	if(i % 5 == 0)
		continue;  
	sum += i;
}

}

上面程序的作用是( 0~99求和,除了5的倍数 )

  1. int main()

{

int number = 0;
while(1)        
{
	scanf("%d", &number);
	if(number == 0)  
	{
		break;    	
	}
}

}

上面程序的作用是( 不停的输入整数,直到输入为0结束 )

  1. for( ; ; ) //for循环只要省略表达式2,就是死循环

上面语句的作用是( 死循环 )

  1. 下面程序的运行结果为( 0 1 2 4 )。

for(k = 0; k < 5; ++k)

{

if(k == 3)  
	continue;
printf("%d",k);

}

作业:

编写shell脚本,实现按键 asdw 控制输出上下左右

#!/bin/bash 

read -p "input asdw: " INPUT
case $INPUT in
	"a")
		echo "左"
		;;
	"s")
		echo "下"
		;;
	"d")
		echo "右"
		;;
	"w")
		echo "上"
		;;
esac

作业:

编写脚本,实现简单的计算功能。 示例: bash a.sh 3 + 4

#!/bin/bash 

case $2 in
	"+")
		echo `expr $1 + $3`
		;;
	"-")
		echo `expr $1 - $3`
		;;
	"x")
		echo `expr $1 \* $3`
		;;
	"/")
		echo `expr $1 / $3`
		;;
esac

1、shell 中的循环

1. for 循环格式:

for NAME in $(单词表)

do

​ 循环语句。

done

单词表是N个字符串的集合,比如 $*是位置参数的集合。

NAME是用来遍历单词表的变量名,在每一次循环体执行中,NAME的值将分别等于单词表的每个单词。

比如:单词表 hehe haha heihei,那么这个for循环将进行3次,在第一次循环体中,NAME 值hehe,在第二次循环体中NAME值是haha,在第三次循环体中NAME值是heihei。

示例:

#! /bin/bash

LIST=“zhao qian sun li zhou”

for NAME in $LIST

do

​ echo $NAME

done

练习:

请输出 根目录下的所有文件名称 使用for循环

#!/bin/bash 

LIST=`ls /`		#把ls /本应打印的结果赋值给变量
for FILE in $LIST
do
	echo $FILE
done

练习:

请使用循环实现,将 day7 目录中的所有文件,都拷贝到 day8 中。(不使用 cp -r )用循环一个一个文件拷贝

#!/bin/bash 

DAY7FILES=`ls day7`
for FILE in $DAY7FILES
do
	cp day7/$FILE day8
done

2. while 循环格式:

while [ 条件 ]

do

​ 循环语句。

done

示例:

vi test.sh

#! /bin/bash

M=1

while [ $M -le 100 ]

do

​ echo “M is $M”

​ M=`expr $M + 1`

done

//输出1~100

练习:

求 1~100 的和。

#!/bin/bash 

SUM=0
M=1
while [ $M -le 100 ]
do
	SUM=`expr $SUM + $M`
	M=`expr $M + 1`
done

echo $SUM

练习:

使用 while 完成功能: 创建 temp1 ~ temp9 九个文件

#!/bin/bash 

M=1
while [ $M -le 9 ]
do
	mkdir temp$M
	M=`expr $M + 1`
done

shell脚本总结

shell脚本是运行在shell上的脚本程序,用来做linux的命令的批处理。

用户 shell 内核 硬件的关系。

linux系统的特点:

多用户

多任务

方便移植

2、 make (工程管理工具)

作用:提高编译效率。

如果是已经编译过的文件,又没有进行修改,下次编译的时候不再编译。

make : 工程管理工具。 make 命令。

makefile : 是配置文件。 是 make 命令唯一读入的配置文件。

makefile 的名字是固定的。

Makefile或者写成makefile都可以。

工作的时候大概率不会从头编写Makefile文件,但是很可能要对它进行修改。

1. 文件编写规则

目标名称:依赖文件

​ 编译规则

//我们以前使用过的编译命令,在这里test是我们要编译的目标,生成这个目标的文件叫test.c,test.c是test的依赖文件。gcc test.c -o test就是编译规则。

gcc test.c -o test

目标名称:编译最终生成的产物。

依赖文件:编译目标需要的文件。

main是目标,main.c add.c del.c是编译这个目标的依赖文件。依赖文件不一定是.c文件。

还可能是.o文件。

编译规则:编译的指令。

示例:

vi makefile

main:main.c

​ gcc main.c -o main

执行过程:

linux@ubuntu:~$ make

添加清除和重新编译的功能:

示例:

vi makefile

teris:teris.c

​ gcc teris.c -o teris

clean:

​ rm teris

rebuild: clean teris

编译规则要和生成的目标名字保持一致。

make

make clean

make rebuild

2. 多文件处理

1)不标准的写法

main:main.c add.c sub.c mul.c

​ gcc main.c add.c sub.c mul.c -o main

linux@ubuntu:~/22011$ make
gcc main.c add.c sub.c mul.c -o main

此时我们修改任意一个源文件,发现会将所有的源文件重新编译。达不到makefile应该发挥的效果。

2)改善写法

main:main.o add.o sub.o mul.o
gcc main.o add.o sub.o mul.o -o main
main.o:main.c
gcc main.c -c
add.o:add.c
gcc add.c -c
sub.o:sub.c
gcc sub.c -c
mul.o:mul.c
gcc mul.c -c

3)简洁的写法

main:main.o add.o sub.o mul.o

​ gcc main.o add.o sub.o mul.o -o main

.o:.c #每个.o文件对应自己同名的.c文件

​ gcc *.c -c

clean:

​ rm *.o main #clean的时候,因为生成多个目标,所以需要清理掉所有的目标,包括所有的.o文件以及main

rebuild: clean main

3. 添加变量

1) 预设变量

$@ : 完整的目标名称

$^ : 依赖文件

$< : 每个.o文件的第一个依赖文件

vi makefile

main:main.o add.o sub.o mul.o

​ gcc $^ -o $@

.o:.c

​ gcc $< -c

clean:

​ rm *.o main

rebuild: clean main

2) 将目标等,用变量代替

EXEC=main #把目标的名称放在一个变量里

OBJS=main.o add.o sub.o mul.o #将所有的依赖文件放在一个变量里

CC=gcc #把使用的编译器也放在变量里

$(EXEC): $(OBJS) # main:main.o add.o sub.o mul.o

​ $(CC) $^ -o $@ # gcc main.o add.o sub.o mul.o -o main

.o:.c

​ $(CC) $< -c # gcc .o文件对应的.c文件 -c

clean:

​ rm $(OBJS) $(EXEC) # main.o add.o sub.o mul.o main

rebuild: clean $(EXEC) # clean main

3、 gdb (调试器 GNU debuger)

为什么使用gdb:当我们的代码出现逻辑问题的时候,需要进行调试,此时我们可以选择一个调试工具辅助我们进行调试。gdb就是一个很有名气的调试器。

调试的思想:

调试代码使用的工具不是最重要,要有调试思想。

1 预判可能出现问题的模块。

2 查看关键位置关键变量的值是否正常。

比如:俄罗斯方块,不自动出方块。预判可能是出方块的代码逻辑有问题。此时,我们可以查看生成方块的随机值、再看看方块起始位置的值。

​ 这是断点的思想!!

gdb 的使用示例:

~$ gcc a.c -o a1

~$ gcc a.c -o a2 -g // 添加 -g 选项。 将调试信息写到了可执行文件里。

~$ ls -l

-rwxrwxr-x 1 linux linux 7157 Aug 3 16:50 a1

-rwxrwxr-x 1 linux linux 8129 Aug 3 16:51 a2 // 因为添加了 -g 选项,所以可执行文件要大一些。

使用: gdb a2 // gdb + 执行文件名

gdb 模式中的一些命令:

l : 列出代码(默认10行)

b : 设置断点 breakpoint

r : run 运行程序

n : next 单步运行

p : print 打印各类变量等信息。

c : continue 继续运行

q : quit 退出 gdb 模式

info break: 查看断点信息

delete 断点号: 删除断点

作业:

一 选择题

1.与十六进制数200等值得十进制数为( B )

10 0000 0000

A:256 B:512 C:1024 D:2048

2.下面哪个shell语句不能打印出用户主目录的路径? ( C )

A. echo “$HOME” B. echo ~

C. echo `$HOME` D. echo $HOME

3.switch语句( A )。

A:都可以用if-else if结构实现 B:都不可以用if-else if结构实现

C:有的可以用if-else if结构实现 D:大部分不可以用if-else if结构实现

4.设有定义:int a,*pa=&a;以下scanf语句中能正确为变量a读入数据的是( A )

A:scanf(“%d”,pa); B:scanf(“%d”,a);

C:scanf(“%d”,&pa); D:scanf(“%d”,*pa);

5.1MB等于( D )

A:1000字节 B:1024字节 C:1000*1000字节 D:1024*1024字节

byte 字节 = 8bit位

6.以下代码打印的结果是(假设运行在i386系列计算机上): ( C )

struct st_t

{

int status;

short* pdata;

char errstr[32];

};

40字节

struct st_t st[16];

char* p = (char*)(st[2].errstr + 32); //st[2].errstr得到st[2]里面的errstr数组名,是地址,地址是char类型

//st[2].errstr + 32地址的偏移运算,正好得到st[3] 的地址,将st[3] 的地址转换成char类型地址赋值给p

printf("%d", (p - (char*)(st))); //st是st[0]的地址,将st[0] 的地址转换成char地址,st[3]地址-st[0]地址相差120个字节,因为 (p - (char*)(st))是以char为地址类型,所以一个单位是一个字节。所以最后得到120个单位

地址相减是什么意思?

int a;
int* p = &a;
printf("%p %p\n", p, p+1);//前后两个地址相差4个字节
//地址1+N = 地址2
//地址2-地址1 = N    所以地址相减得到偏移的单位数

A 32 B 114

C 120 D 1112

二:填空

1.C语言源代码编译成a.out的过程中需要经历哪些过程_________预处理 编译 汇编 链接_____。(东软)

2.C 语言运算对象必须是整型的运算符是___%________。(东软)

3.有一个参数为char*,返回值也为char*的函数f,需要定义一个函数指针a,指向函数f,

请写出函数指针a的定义___char *(*a)(char *);_______。

作业:

编一个程序求质数的和,

例如F(7)= 2+3+5+7+11+13 +17 = 58 (笔试综合)

#include <stdio.h>

int isPrime(int num)
{
	int i;
	for(i = 2;i < num;i++)
	{
		if(num%i == 0)
		{
			return 0;
		}
	}
	return 1;
}

int main()
{
	int i;
	int n;
	scanf("%d", &n);
	int num = 2;
	int sum = 0;
	for(i = 0;i < n;)
	{
		if(isPrime(num) == 1)
		{
			sum += num;
			i++;
		}
		num++;
	}
	printf("%d\n", sum);
	return 0;
}

作业:(选做,不讲)

编写一个弹出式菜单的shell程序并实现其简单的菜单功能


​ * MENU *

​ * 1.copy 2.rename *

​ * 3.remove 4.exit *


即用户按下数字1,复制

输入数字2,改名

输入数字3 删除

1.C语言源代码编译成a.out的过程中需要经历哪些过程_________预处理 编译 汇编 链接_____。(东软)

2.C 语言运算对象必须是整型的运算符是___%________。(东软)

3.有一个参数为char*,返回值也为char*的函数f,需要定义一个函数指针a,指向函数f,

请写出函数指针a的定义___char *(*a)(char *);_______。

作业:

编一个程序求质数的和,

例如F(7)= 2+3+5+7+11+13 +17 = 58 (笔试综合)

#include <stdio.h>

int isPrime(int num)
{
	int i;
	for(i = 2;i < num;i++)
	{
		if(num%i == 0)
		{
			return 0;
		}
	}
	return 1;
}

int main()
{
	int i;
	int n;
	scanf("%d", &n);
	int num = 2;
	int sum = 0;
	for(i = 0;i < n;)
	{
		if(isPrime(num) == 1)
		{
			sum += num;
			i++;
		}
		num++;
	}
	printf("%d\n", sum);
	return 0;
}

作业:(选做,不讲)

编写一个弹出式菜单的shell程序并实现其简单的菜单功能


​ * MENU *

​ * 1.copy 2.rename *

​ * 3.remove 4.exit *


即用户按下数字1,复制

输入数字2,改名

输入数字3 删除

. 输入数字4,退出

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

encounter♌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值