Linux C语言编程基本原理与实践

2020-12-11  本文已影响0人  前端程序猿

一、C 语言是什么?

C 语言是一个有结构化程序设计、具有变量作用域以及递归功能的过程式语言。广泛用于系统软件与应用软件的开发。

C 语言,通俗的讲,就是人类和计算机交流的一种方式。

1.1 ANSI C

ANSI C、ISO C、Standard C 是指美国国家标准协会(ANSI)和国际标准化组织(ISO)对 C 语言发布的标准。历史上,这个名字专门用于指代此标准的原始版本,也是支持最好的版本(称为 C89 或 C90)

1.2 C 语言的特点

1.3 C 语言适合做什么?

什么样的程序最有价值?
什么样的场景最适合用 C 语言

二、开发环境与配置

2.1 准备一个 linux 环境

2.2 编辑器

2.3 安装 vim

yum install vim

2.4 查看 cc 编译器

cc -v

显示当前的 cc 编译器是 gcc 版本,gcc 是兼容 cc 的编译器

gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC)

也可以使用这条命令查看

gcc -v

三、Linux 下的第一个C程序

3.1 创建工程目录以及编辑 C 程序文件

mkdir less1
cd less1
vim a.c

3.2 hello world

#include <stdio.h> // 导入标准的输入输出流 头文件

int main()
{
  printf("hello world\n");
  return 0;
}

保存并退出

3.3 编译 c 程序

cc a.c

会生成 a.out 的可执行文件

3.4 执行编译后的 c 程序

./a.out

结果在命令行输出

[root@VM_0_3_centos less1]# ./a.out
hello world

四、多文件操作

4.1 函数文件和入口文件分别定义

int max(int a, int b) {
  if (a > b) {
    return a;
  } else {
    return b;
  }
}
int min(int a, int b) {
  if (a > b) {
    return b;
  } else {
    return a;
  }
}
#include <stdio.h> // 系统库中查找
#include "max.c" // 当前项目中查找
#include "min.c" // 当前项目中查找

int main() {
  int a  = 12;
  int b = 20;
  int maxNum = max(a, b);
  int minNum = min(a, b);
  printf("the max value is %d\n", maxNum);
  printf("the min value is %d\n", minNum);
  return 0;
}
gcc main.c -o main.out

./main.out

4.2 引用编译后的函数文件

当入口文件中引入很多自定义的 C 源程序代码时,一起编译时会很慢,如果引入的是编译后的文件,编译就会很快了

gcc -c max.c -o max.o
gcc -c min.c -o min.o
#include <stdio.h> // 系统库中查找
// #include "max.c" // 当前项目中查找
// #include "min.c"
gcc min.o max.o main.c -o main.out
./main.out

4.3 编写头文件

使用编译后的文件与入口函数一起编译时,能够加快编译速度,但是却看不到编译文件中的函数的用法,因此需要编写编译文件的头文件,让别人知道该编译文件的使用方法

int max(int a, int b);
int min(int a, int b);
#include <stdio.h> // 系统库中查找
// #include "max.c" // 当前项目中查找
// #include "min.c"
#include "max.h"
#include "min.h"

五、 Makefile 的编写和使用

如果我们在编译时,引入了有很多个编译文件

gcc min.o max.o main.c -o main.out

命令行就会变得很长很长,这种方式就不可行了,这时我们需要来编写 MakeFile

5.1 make 命令

查看 make 工具是否已经安装

make -v

5.2 编写 Makefile

# main.out 是目标文件, 依赖于 min.o max.o main.c
# 通过执行 gcc min.o max.o main.c 生成 main.out
main.out:min.o max.o main.c
        gcc min.o max.o main.c -o main.out
# 如果缺少 min.o max.o, 需要先执行下面的命令生成 min.o max.o
# 如果 min.o max.o 已经存在, 再次编译时,就不会再生成 min.o max.o 了
# 如果 min.o 或 max.o 做了修改,再次编译时,也会重新生成 min.o 或 max.o
# min.o 是目标文件,依赖 min.c
# 通过执行 gcc -c min.c 生成 min.o
min.o:min.c
        gcc -c min.c
# max.o 是目标文件,依赖 max.c
# 通过执行 gcc -c max.c 生成 max.o
max.o:max.c
        gcc -c max.c

5.3 执行 Makefile 生成目标文件

make Makefile

./main.out

六、 main 函数的详解

6.1 main 函数中的 return

[root@VM_0_3_centos less2]# ./a.out
hello world
[root@VM_0_3_centos less2]# echo $?
0

输出 0 表示上一条命令执行成功, 而 0 也是 main 函数里的返回结果

./a.out && ls

上面的命令,会接着执行 ls

如果 main 函数的返回值不为 0, 表示程序执行失败

int main(int argv, char* argc[]) {
  printf("hello world \n");
  return 1;
}

编译运行后的结果:

[root@VM_0_3_centos less2]# ./a.out
hello world
[root@VM_0_3_centos less2]# echo $?
1
./a.out && ls

上面的命令,不会接着执行 ls

6.2 main 函数中的参数

main 函数的完整形式

// argv 表示命令行参数的个数
// argc 表示命令行参数组成的字符串数组
int main(int argv, char* argc[]) {
  printf("argv is %d\n", argv);

  int i;
  for (i = 0; i < argv; i++) {
    printf("argc[%d] is %s\n", i, argc[i]);
  }
  return 0;
}

编译并运行的结果:

[root@VM_0_3_centos less2]# ./a.out -a -b
argv is 3
argc[0] is ./a.out
argc[1] is -a
argc[2] is -b

七、 输入流、输出流、错误流

7.1 标准输入流输出流以及错误流

#include <stdio.h>

int main() {
  // stdout 标准输出流
  // printf("Please input a number: \n");
  fprintf(stdout, "Please input a number: \n");

  int a;
  // stdin 标准输入流
  // scanf("%d", &a);
  fscanf(stdin, "%d", &a);

  if (a < 0) {
    // stderr 标准错误流
    fprintf(stderr, "the inputed value must be greater than 0\n");
    return 1;
  }
  return 0;
}

7.2 输入流输出流以及错误流的重定向

#include<stdio.h>

int main() {
        int i, j;
        printf("please input value a: \n");
        scanf("%d", &i);
        printf("please input value b: \n");
        scanf("%d", &j);
        if (j == 0) {
                fprintf(stderr, "the value of j can't equal to 0\n");
                return 1;
        } else {
                printf("%d/%d=%d\n", i, j, i/j);
        }
        return 0;
}

1 表示输出流,默认值,可以不写

./a.out 1> stdout.txt
./a.out > stdout.txt

编译并运行

[root@VM_0_3_centos less2]# ./a.out > stdout.txt
1
1
[root@VM_0_3_centos less2]# cat stdout.txt
please input value i:
please input value j:
1/1=1
./a.out 1>> stdout.txt

文件内容为
stdin.txt

8
4

0 表示输入流, 默认值, 可以不写

./a.out <0 stdin.txt
./a.out < stdin.txt

编译并运行

[root@VM_0_3_centos less2]# ./a.out < stdin.txt
please input value i:
please input value j:
8/4=2
./a.out 2>> stderr.txt

编译并运行

[root@VM_0_3_centos less2]# ./a.out 2>> stderr.txt
please input value i:
1
please input value j:
0
[root@VM_0_3_centos less2]# cat stderr.txt
the value of j can't equal to 0
./a.out 1>> stdout.txt 2>> stderr.txt <0 stdin.txt

八、 使用管道打造实用的C语言程序

8.1 什么是管道?

将前一个命令的输出流, 作为下一个命令的输入流

查看 /etc/ 包含 ab 的文件

ls /etc/ | grep ab

查看是否开启了 ssh 进程

ps -e | grep ssh

8.2 使用管道计算平均值

input.c

#include<stdio.h>

int main() {
        int i;
        int count = 0;
        int sum = 0;
        while(1) {
                scanf("%d", &i);
                if (i == 0) {
                        printf("%d,%d\n", sum, count);
                        break;
                }
                sum += i;
                count++;
        }
        return 0;
}

avg.c

#include <stdio.h>

int main(){
 int s = 0;
 int n = 0;
 scanf("%d,%d", &s, &n);
 float v = s / n;
 printf("avg = %f\n", v);
 return 0;
}

编译并运行

[root@VM_0_3_centos less3]# ./input.o | ./avg.o
5
98
0
avg = 51.000000
上一篇 下一篇

猜你喜欢

热点阅读