再学C语言,复习&笔记。
系列顺序:
Linux C语言编程基本原理与实践
Linux C语言指针与内存
Linux C语言结构体
更多Linux知识:
一天一点linux
常用指令
sudo
管理员权限sudo apt-get update
更新资源(安装软件前最好先更新资源)sudo apt-get install vim(软件名称)
安装某软件cd ~
进入home目录pwd
显示当前目录路径ls
显示当前文件夹下所有文件夹及文件ls -l
进入当前目录的文件夹目录后查看当前文件夹包含的文件/文件夹的类型、创建时间、用户权限、用户和用户组
(最前面是“d”为文件夹;“-”为普通类型的文件)touch + 文件名
新建文件rm + 文件名
删除文件mkdir + 目录名
新建目录vi(vim) + 文件名
使用vim编辑文件clear
清洁屏幕cc -v
检查编译器gcc -v
检查编译器
VIM命令模式:dd
删除整行i
在光标前面插入a
在光标后面插入x
删除单个字符Shift + a
行尾插入Shift + i
行首插入o
下一行插入Shift + o
上行插入:$
跳到代码末尾
第一个Linux C程序
编译文件:1
cc a.c
会得到a.out
编译文件后查看文件权限:
rw-:可读、可写
rwx:可读、可写、可执行
三个rwx 1创建用户 2与创建用户在同一个用户组 3任意用户
运行文件:
“.” 当前路径
“./” 当前路径下的文件
执行文件:./a.out
多文件操作
sp max.c
新建max.c文件(窗口打开多个文件)ctrl + w +下箭头
跳转到下一个编辑框ctrl + w +下箭头
跳转到上一个编辑框对应行数+d+d
剪切光标下相应行数的程序
9dd(代码占九行,剪切代码)
按p
粘贴在剪切板的程序set nu
打开行号:wqa
保存所有文件并退出1
2
3gcc hello.c -o hello.out 指定编译文件(-o 给编译后的文件重命名)
cp a.c b.c 拷贝文件:将a.c拷贝到b.c
cat a.c 查看源代码程序
分开编译:1
gcc -c 文件名.c -o 文件名.o
函数可以先编译成.o文件,然后再和主文件一起编译成可执行文件。在源代码多的时候可以提高效率。
例如:1
2
3
4
5
6
7
8gcc -c max.c -o max.o
gcc max.o hello.c
./a.out
cp max.c min.c
rm a.out
gcc-c min.c -o min.o
gcc gcc max.o min.o hello.c
./a.out
gcc编译流程分为4步:
预处理(Pre-Processing) -> 编译(Compling) -> 汇编(Assembling) -> 连接(Linking)
预处理:处理#include、#define、#ifdef 等宏命令
编译:把预处理完的文件编译为汇编程序.s
汇编:把汇编程序.s编译为.o二进制文件
链接:把多个二进制文件.o集合(链接)成一个可执行文件
使用别人的静态库.o文件(机器码,无法查看原代码)可以创建.h文件,然后在源程序中#include<文件名.h>来引用。
hello.c1
2
3
4
5
6
7
8
9
10
11
12
13
int main()
{
int a1 = 33;
int a2 = 21;
int maxNum = max(a1, a2);
int minNum = min(a1, a2);
printf("%d,%d\n", maxNum, minNum);
return 0;
}
max.c1
2
3
4
5
6
7
8int max(int a, int b)
{
if(a > b){
return a;
}else{
return b;
}
}
min.c1
2
3
4
5
6
7
8int min(int a, int b)
{
if(a < b){
return a;
}else{
return b;
}
}
max.h1
int max(int a, int b);
min.h1
int min(int a, int b);
makeFile的编写与使用
make工具可以将大型的开发项目分成若干个模块。
make工具可以很清晰和很快捷的编译和整理源文件。
rm *.o
表示删除所有.o文件make -v
检查make版本
vi Makefile 编译修改过的部分
输出文件:源文件
一个tab gcc命令
从上到下逐层求精
eg:1
2
3
4
5
6hello.out:max.o min.o hello.c
gcc max.o min.o hello -o hello.out
max.o:max.c
gcc -c max.c
min.o:min.c
gcc -c min.c
最后用make命令执行
重复使用make时,中间生成过的文件不需要再生成,没有修改过的文件不用再编译,会直接跳过该段代码,所以更加节省编译时间。
gcc-c
参数的意义:-c
参数是将源代码编译成“目标文件 .o”,不进行连接
后面多个目标文件可通过-o链接成可执行文件。
不使用这个参数时gcc会直接进行编译链接,生成可执行文件。
main函数详解
1 |
|
gcc main.c -o main.out && ./ main.out
echo \$? 执行成功则返回0
参数1
2
3
4
5
6
7
8
9int main(int argc,char* argv[])
{
printf("argc is %d\n",argc);
int i;
for(i=0;i<argv;i++){
printf("argv[%d] is %s\n",i,argv[i]);
}
return 0;
}
./out.c -l -s asd qwe
输出为:1
2
3
4
5
6argc is 5
argv[0] is ./m3.out
argv[1] is -l
argv[2] is -a
argv[3] is asd
argv[4] is qwe
标准输入流输出流以及错误流
cio.c1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
stdin
stdout
stderr
*/
int main()
{
printf("hello world!\n"); //输出功能由标准输出流完成,printf是系统封装后的
int a;
scanf("%d", &a); //标准输入流,错误流是系统出错的时候的
printf("input value is : %d\n", a);
return 0;
}
在输入a.out时,程序执行,系统给程序提供了一个进程,当程序启动时,系统也提供给程序一系列的指针。linux将所有的外设(摄像头,打印机等),都视为文件。当启动应用程序时候,会产生三个文件(stdin,stdout,stderr,即标准输入,输出,错误流)。
默认情况下,输入流就是键盘,stdout默认为显示器,可切换为网卡或者打印机。
1 | printf("Please input the value a:\n"); |
因为stdout默认是显示器,上两句就是等价的,printf其实就是fprintf封装后得到的。
同理,scanf和fscanf等价:1
2scanf("%d", &a);
fscanf(stdin, "%d", &a);
错误流:1
2
3
4
5if(a < 0){
fprintf(stderr, "the value must > 0\n");
return 1;
}
return 0;
通过返回值1和0,让程序知道出错了。再次编译cc cio.c -o a2.out,我们运行a2.out,输入2则正常执行,当输入-1,则有对应的提示,即错误流发挥作用。
其实Linux这个很大的系统,就是由这些类似的小工具完成的。当等于0是为正确,错的话为其他值。
标准的输入流,输出流,以及错误流还可以重定向。
Linux几乎可以用于任何领域,这里我们不得不提出linux的通道,管道起到了很重要的作用,不同应用程序之间要配合使用,就需要用到管道。
先说输入流,输出流和错误流的重定向机制:1
2
3
4
5
6
7
8
9
10
int main()
{
printf("input the int value i:\n"); \\printf其实对fprintf的封装,是从标准输出流(即stdout)来输出这个过程
scanf("%d", &i); //默认输入流是键盘
printf("input the int value j:\n");
scanf("%d", &j);
printf("i+j=%d\n", i+j);
}
cc main.c
得到a.out,运行a.out,我们分别输入3和5输入到终端。我们标准输出流是1,输出入是0。>>
标准输出流重新定向符1
2
3./a.out 1>> a.txt 输出到a.txt(默认为1,可不写1)
./a.out >> a.txt 内容追加下方
./a.out > a.txt 内容覆盖
执行命令后,分别输入3回车后再输入5。再使用命令cat a.txt,可以看到已经输出到文件里的内容。
错误流重定向:1>标准输出流重定向 2>标准错误流重定向
./a.out 1>t.txt 2>f.txt 将正确的输出流重定向输出到t.txt,错误的输出流重定向输出到f.txt
<<
标准输入流重新定向符1
./a.out < input.txt 将input.txt的内容作为输入流传递给程序a.out
综合使用标准输出流、标准错误流、标准输入流1
./a.out 1>t.txt 2>f.txt <input.txt
管道原理及应用
ls /
查看根目录ls /etc/
查看Linux默认配置目录ls /etc/ | grep 关键字符
将etc文件输出到一个管道|
管道
eg. 要查找某个目录下有多少个文件名包含“ab”,可以写1
ls /etc/ | grep ab
将前一个程序输出流重定向到grep,通过管道得到需要的内容。
ps -e | grep ssh
ps查看当前的进程,当前操作系统是否开启ssh进程
管道使用demo
程序avg.c,求任意个数的平均值:1
2
3
4
5
6
7
8
9
10
int main()
{
int sum, n;
scanf("%d,%d", &sum, &n);
float v = sum / n;
printf("v = %f\n", v);
return 0;
}
cc avg.c -o avg.out
再写一个统计输入的程序input.c:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int main()
{
int flag = 1;
int i;
int count = 0;
int sum = 0;
while(flag){
scanf("%d", &i);
if(0==i){
break;
}
count++;
sum+=i;
}
printf("%d,%d\n",sum,count);
return 0;
}
cc input.c -o input.out
结合使用以上两个程序,将所有数据进行统计,执行input.out,之后通过管道经过avg.out计算平均值。
./input.out | ./avg.out
以上就是通过管道,将两个小程序连接起来得到更复杂的程序的过程。