Lab0课下的基础教程,比较简单,主要分为四个部分:
- Exercise0.1
- Exercise0.2
- Exercise0.3
- Exercise0.4
Exercise0.1
第一小问是C语言基础编程的考察,我的思路是把整数n的各个位置上的数字取出存入数组中,然后在数组中从首尾至中间进行比较即可
int flag = 1;
if(n<10)flag=1;
else{
int arr[10]={0},cnt=0;
while(n){
arr[cnt++]=n%10;
n/=10;
}
int s_cnt=0;
cnt--;
while(s_cnt<cnt){
if(arr[s_cnt]==arr[cnt]){
cnt--;s_cnt++;
}else{
flag=0;
break;
}
}
}
if (flag) {
printf("Y\n");
} else {
printf("N\n");
}
第二小问考察的知识点是Makefile,本身也不难,要求在该目录下使用make即可进行编译,那么第一个构建的目标就是palindrome
palindrome: palindrome.c
gcc palindrome.c -o palindrome
第三小问考察的是linux shell的基础知识点,只要熟练掌握shell语法即可
首先是对于文件特定行的查看,可以使用
sed -n "1p" filename
其中sed默认输出每一行,而-n代表关闭默认输出,-p代表打印对应的行数(补充:"1,3p"表示打印1至3行,"1p;3p;5p"表示打印1,3,5行)
其次是第四小问,考察shell脚本的相关知识点,假设我们执行命令行./script.sh AAA BBB,那么./script.sh就是$0,AAA和BBB依次是$1和$2
所以在script.sh中,我们使用$1就可以代表AAA,$2代表BBB
sed -n "8p;32p;128p;512p;1024p" "$1" > "$2"
其中>表示重定向,把原本要输入到终端屏幕的标准输出改成输出到指定文件中,每次就覆盖内容,而>>表示追加内容不覆盖
最后就是文件的复制,我们使用cp -r source dst其中-r表示递归复制
cp -r ~/12345678/src/* ~/12345678/dst/
其中我使用的是绝对路径
Exercise0.2
考察shell的基本语法,在shell脚本中,我们可以定义
a=1
后续访问具体数值时我们需要使用$a
为了访问1至100的所有数值,我们使用循环while
while [ $a -le 100 ]
do
a=$((a+1))
done
也可以使用for循环
for((a=1;a<=100;a++))
do
continue
done
如果需要使用条件判断if我们可以使用
if condition
then
comand1
comand2
......
elif condition
then
command1
elif
then
commmand1
else
command1
done
其中if和elif都需要紧跟then,而else则不用
创建文件时我们使用
mkdir filename
删除文件时我们使用
rm -rf filename
修改文件名时我们使用
mv filename_old filename_new
所以我们可以写出循环内部的逻辑
if((a>70)) #or [ $a -gt 70 ]
then
rm -rf "file$a"
elif((a>40)) #or [ $a -gt 40 ]
then
mv "file$a" "newfile$a"
done
补充一些细节:
[ $a -gt 70 ]首尾要留空格,不然会报错bash中可以使用((condition))进行条件判断,如果条件为真,返回0,否则返回1bash中可以使用$((expression))进行算术运算,比如已知a=1,执行b=$((a+1)),可以得到b=2,如果执行b=a+1,可以得到b=a+1,也即shell不会自动解析变量名字
Exercise0.3
本题前置知识点grep
grep -n "int" filename
表示搜索文件filename中含有字符串"int"的行,-n表示输出行号
更多地,如果后面是一个文件夹,可以使用-r表示递归搜索文件,有时我们也使用-R表示同时也搜索子文件夹中的链接目录
前置知识点cut
假设我们使用grep -n "echo" msg.sh得到
2: echo "$1" 3: echo "$2" 4: echo "the number of parameters is $#"
但是我们只想要得到前面的行号,可以这样
grep -n "echo" msg.sh | cut -d: -f1
管道|代表把上一个命令的输出作为下一个命令行的输入,cut则会切割输入,-d:表示按照:进行切割,-f1表示只取第一列的结果(基数从1开始),而-f1,3表示取第1列和第三列,-f1-4表示取1至4列
所以我们最后可以得到
grep -n "$2" "$1" | cut -d: -f1 > "$3"
或者我们也可以使用awk
grep -n "$2" "$1" | awk -F: '{print $1}' > "$3"
这里awk的用法中,-F:表示按照:拆分行,后续的$0 $1 $2分别代表整行、第一列、第二列,以此类推
此外值得注意的是这里建议使用单引号,如果使用双引号,那么shell脚本会先解析$1,如果你先前没有定义,那么实际传入awk的是print , 从而打印整行
Exercise0.4
第一部分要求我们使用命令行对文件进行修改,推荐使用sed
前面我们说过sed -n或者sed都只会在终端输出,没有改变原文件,要改变原文件,我们可以使用-i表示重定向输出到原文件,也就是覆盖
此外,我们还要使用"s/str1/str2/"进行操作,表示替换每行中的第一个str1为str2,如果是"s/str1/str2/g"表示替换全部,如果是"s/str1/str2/p"对于每一行,如果发生替换就打印
于是我们得到
sed -i "s/$2/$3/g" "$1"
第二部分是对于Makefile的进一步操作
all:
make -C filedir
表示进入filedir中进行make操作,等价于
cd filedir make
于是我们得到外层csc/Makefile
all:
make -C code
clean:
make -C code clean
对于内层code/Makefile
all: fibo
fibo: fibo.o main.o
gcc fibo.o main.o -o ../fibo
fibo.o: fibo.c
gcc -I ../include -c fibo.c
main.o: main.c
gcc -I ../include -c main.c
clean:
rm -rf fibo.o main.o
这里补充几点:
每次执行make时,每当执行到:
all: fibo
make会检查./fibo,但是我们实际生成的是../fibo,系统无法找到,所以该命令行每次都会执行
所以可以这样写
all: ../fibo
../fibo: fibo.o main.o
gcc fibo.o main.o -o ../fibo
建议target必须与生成文件一致
target: dependencies
command
此外需要注意的是command前面一定是tab不能使用空格代替,本文中为编辑方便不保证command前面都是tab
最后补充一下gcc -I ../include意思就是指定头文件搜索路径,因为通常GCC只会找当前目录和系统头文件目录(/usr/include),我们通常要给它指定额外的路径,这里再补充一下,在Makefile中-I的基准目录就是Makefile所在的目录,因此后面可以跟相对路径
此外,值得注意的是gcc -c file.c将生成object module也就是*.o文件,而gcc -S file.c将生成assembly code也就是*.s文件,gcc -E file.c只执行预处理,输出预处理结果(可保存为*.i文件)
GCC 实际有四个阶段:
file.c ↓ 预处理 (-E) file.i ↓ 编译 file.s ↓ 汇编 file.o ↓ 链接 a.out

Comments NOTHING