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

简介: 笔记:Linux C语言编程基本原理与实践

C语言的应用:

1、Linux嵌入式(小工具)(C语言小巧灵活、语法简单、适合做小工具)

linux/unix系统就是由各种各样的小工具集成得来的。


2、和硬件打交道的程序

a、操作系统:苹果系统,安卓系统,windoows

b、ARM嵌入式、单片机、Arduino


3、有高性能要求的应用程序

著名的WEB服务器,NGINX=apache*10


环境

centos https://www.centos.org/

ubuntu https://ubuntu.com/

常用指令

# ubuntu 安装vim编辑器
$ apt-get update
$ apt-get install vim
# 编译器
$ cc -v
$ gcc -v

VIM命令模式


i    (插入模式 或 当前光标前插入字符)
Esc     (返回命令行模式)
:w    (保存)
a    (当前光标后插入字符)
:q     (退出VIM)
Shitf + a   (在行尾插入字符)
Shift + i   (在行手插入字符)
o      (下一行插入字符)
Shift + o   (在当前行上行插入字符)
x     (删除单个字符)
dd    (删除整行字符)

C程序

hello.c

#include <stdio.h>
int main(){
    printf("hello world\n");
    return 0;
}

编译执行


# 编译
$ cc hello.c 
# 或者
$ gcc hello.c
# 执行
$ ./a.out

代码分布在多个源文件

1、放在一个文件


hello.c


#include <stdio.h>  // 系统目录中查找
int max(int a, int b){
    if (a > b) {
        return a;
    } else {
        return b;
    }
}
int main(){
    int a = 1;
    int b = 2;
    int ret = max(a, b);
    printf("max value is %d\n", ret);
    // max value is 2
    return 0;
}

编译执行 执行输出文件,默认是a.out


$ gcc hello.c -o hello.out
$ ./hello.out

2、放在多个文件


hello.c


#include <stdio.h>  // 系统目录中查找
int main(){
    int a = 1;
    int b = 2;
    int ret = max(a, b);
    printf("max value is %d\n", ret);
    // max value is 2
    return 0;
}

max.c


int max(int a, int b){
    if (a > b) {
        return a;
    } else {
        return b;
    }
}

多文件编译执行


$ gcc max.c hello.c -o hello.out
$ ./hello.out

此时会有警告


3、声明引用


hello.c


#include <stdio.h>  // 系统目录中查找
#include "max.c"    // 相对目录中查找
int main(){
    int a = 1;
    int b = 2;
    int ret = max(a, b);
    printf("max value is %d\n", ret);
    // max value is 2
    return 0;
}

编译执行


$ gcc hello.c -o hello.out
$ ./hello.out

头文件与函数定义分离

1、两个文件分别编译


gcc参数:


-c compile 只编译源文件但不链接 *.o
-o out 指定输出文件名 默认a.out

分开编译需要注释include


#include <stdio.h>  // 系统目录中查找
// #include "max.c"    // 相对目录中查找
int main(){
    int a = 1;
    int b = 3;
    int ret = max(a, b);
    printf("max value is %d\n", ret);
    // max value is 2
    return 0;
}

编译源文件


# 先编译max.c文件
$ gcc -c max.c -o max.o
# 再编译hello.c文件
$ gcc max.o hello.c

2、三个文件分别编译


min.c


int min(int a, int b){
    if (a > b) {
        return a;
    } else {
        return b;
    }
}

hello.c


#include <stdio.h>
int main(){
    int a = 1;
    int b = 3;
    int maxValue = max(a, b);
    printf("max value is %d\n", maxValue);
    int minValue = min(a, b);
    printf("min value is %d\n", minValue);
    return 0;
}
# 编译min.c
$ gcc -c min.c
# 编译hello.c
$ gcc min.o max.o hello.c -o hello.out

3、引入头文件


min.h


int min(int a, int b);

max.h


int max(int a, int b);

hello.c


#include <stdio.h>  // 系统目录中查找
#include "min.h"    // 引入头文件
#include "max.h"    
int main(){
    int a = 1;
    int b = 3;
    int maxValue = max(a, b);
    printf("max value is %d\n", maxValue);
    int minValue = min(a, b);
    printf("min value is %d\n", minValue);
    return 0;
}

编译执行


$ gcc min.o max.o hello.c -o hello.out
$ ./hello.out

Makefile

# 删除所有.o结尾的文件
$ rm *.o

make工具可以将大型的开发项目分成若干个模块


make内部使用了gcc


$ apt-get install make
$ make -v

Makefile 使用tab缩进


# 注释
hello.out:max.o min.o hello.c
    gcc max.o min.o hello.c -o hello.out
max.o:max.c
    gcc -c max.c
min.o:min.c
    gcc -c min.c

执行编译


$ make

main函数中的return

main.c


# include <stdio.h>
int main(int argv, char* argc[]){
    printf("hello world\n");
    return 0;
}

查看程序返回


# 编译并执行程序
gcc main.c -o main.out && ./main.out
# 查看程序运行结果
$ echo $?

main函数中的参数

main.c


# include <stdio.h>
int main(int argv, char* argc[]){
    for(int i=0; i < argv; i++){
        printf("argc[%d]=%s\n", i, argc[i]);
    }
    return 0;
}
$ ./main.out name age
argc[0]=./main.out
argc[1]=name
argc[2]=age

argv 参数的个数

argc 参数的内容


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

# include <stdio.h>
int main(){
    // 接收输入
    int a;
    scanf("%d", &a);
    // 输出数据
    printf("input value is %d\n", a);
    return 0;
}
stdin  标准输入 eg: 键盘输入
stdout 标准输出 eg: 终端输出
stderr 标准错误 eg: 错误输出
# include <stdio.h>
int main(){
    // printf("please input a value\n");
    fprintf(stdout, "please input a value\n");
    int a;
    // scanf("%d", &a);
    fscanf(stdin, "%d", &a);
    if(a < 0){
        fprintf(stderr, "the value must > 0\n");
        return 1;
    } else{
        return 0;
    }
}

标准输入输出流以及错误流重定向

加法计算器小程序


接收两个输入,计算两个数字的和,并输出


#include <stdio.h>
int main(){
    int a; 
    int b;
    printf("input a:\n");
    scanf("%d", &a);
    printf("input b:\n");
    scanf("%d", &b);
    int ret = a + b;
    printf("a + b = %d\n", ret);
    return 0;
}

1、输出流重定向

# 追加
$ ./mian.out 1>> a.txt 
# 或者
$ ./mian.out >> a.txt 
# 覆盖
$ ./mian.out > a.txt

输出结果 a.txt


input a:
input b:
a + b = 8

2、输入流重定向


输入文件 input.txt

3
4
$ ./main.out < input.txt
input a:
input b:
a + b = 7

3、错误流重定向


#include <stdio.h>
int main(){
    int a;
    printf("input value:\n");
    scanf("%d", &a);
    if( a > 0){
        printf("value %d > 0\n", a);
        return 0;
    } else{
        fprintf(stderr, "value %d < 0\n", a);
        return 1;
    }
}
$ ./main.out 1>stdout.txt 2>stderr.txt

4、同时操作标准输入、标准输出、错误流

stdin.txt


-10

执行程序

$ ./main.out 1>stdout.txt 2>stderr.txt < stdin.txt

stdout.txt


input value:

stderr.txt


value -10 < 0:

管道原理及应用

前一个命令的输出,作为后一个命令的输入

# 查看当前目录下文件
ls
# 查看根目录下文件
ls / 
# 查看/etc目录下文件
ls /etc
# 在/etc目录下查找包含ab字符的文件名
ls /etc | grep ab
# 查询进程
ps -e | grep ssh

sum.c


#include 
/**
对输入求和,并输出求和结果和输入个数
格式:sum:count
eg: 400,2
*/
int main(){
    int sum = 0;
    int count = 0;
    int var;
    while(1){
        scanf("%d", &var);
        if(var == 0){
            break;
        } else{
            sum += var;
            count++;
        }
    }
    printf("%d,%d\n", sum, count);
    return 0;
}

avg.c


#include 
/**
对输入计算平均值
格式:sum,count
eg: 500,2
输出:250.000
*/
int main(){
    int sum;
    int count;
    scanf("%d,%d", &sum, &count);
    float avg = sum / count;
    printf("%f\n", avg);
    return 0;
}

input.txt


500
400
600
0
# 编译
$ gcc sum.c -o sum.out
$ gcc avg.c -o avg.out
# 通过重定向输入和管道处理,先求和再计算平均值
$ ./sum.out < input.txt | ./avg.out
500.000000


相关文章
|
5月前
|
监控 Linux 应用服务中间件
Linux多节点多硬盘部署MinIO:分布式MinIO集群部署指南搭建高可用架构实践
通过以上步骤,已成功基于已有的 MinIO 服务,扩展为一个 MinIO 集群。该集群具有高可用性和容错性,适合生产环境使用。如果有任何问题,请检查日志或参考MinIO 官方文档。作者联系方式vx:2743642415。
1752 57
|
7月前
|
安全 Linux
【Linux】阻塞信号|信号原理
本教程从信号的基本概念入手,逐步讲解了阻塞信号的实现方法及其应用场景。通过对这些技术的掌握,您可以更好地控制进程在处理信号时的行为,确保应用程序在复杂的多任务环境中正常运行。
272 84
|
9月前
|
存储 C语言
【C语言程序设计——函数】递归求斐波那契数列的前n项(头歌实践教学平台习题)【合集】
本关任务是编写递归函数求斐波那契数列的前n项。主要内容包括: 1. **递归的概念**:递归是一种函数直接或间接调用自身的编程技巧,通过“俄罗斯套娃”的方式解决问题。 2. **边界条件的确定**:边界条件是递归停止的条件,确保递归不会无限进行。例如,计算阶乘时,当n为0或1时返回1。 3. **循环控制与跳转语句**:介绍`for`、`while`循环及`break`、`continue`语句的使用方法。 编程要求是在右侧编辑器Begin--End之间补充代码,测试输入分别为3和5,预期输出为斐波那契数列的前几项。通关代码已给出,需确保正确实现递归逻辑并处理好边界条件,以避免栈溢出或结果
400 16
|
9月前
|
算法 C语言
【C语言程序设计——循环程序设计】求解最大公约数(头歌实践教学平台习题)【合集】
采用欧几里得算法(EuclideanAlgorithm)求解两个正整数的最大公约数。的最大公约数,然后检查最大公约数是否大于1。如果是,就返回1,表示。根据提示,在右侧编辑器Begin--End之间的区域内补充必要的代码。作为新的参数传递进去。这个递归过程会不断进行,直到。有除1以外的公约数;变为0,此时就找到了最大公约数。开始你的任务吧,祝你成功!是否为0,如果是,那么。就是最大公约数,直接返回。
225 18
|
9月前
|
Serverless C语言
【C语言程序设计——循环程序设计】利用循环求数值 x 的平方根(头歌实践教学平台习题)【合集】
根据提示在右侧编辑器Begin--End之间的区域内补充必要的代码,求解出数值x的平方根;运用迭代公式,编写一个循环程序,求解出数值x的平方根。注意:不能直接用平方根公式/函数求解本题!开始你的任务吧,祝你成功!​ 相关知识 求平方根的迭代公式 绝对值函数fabs() 循环语句 一、求平方根的迭代公式 1.原理 在C语言中,求一个数的平方根可以使用牛顿迭代法。对于方程(为要求平方根的数),设是的第n次近似值,牛顿迭代公式为。 其基本思想是从一个初始近似值开始,通过不断迭代这个公式,使得越来越接近。
191 18
|
9月前
|
C语言
【C语言程序设计——循环程序设计】统计海军鸣放礼炮声数量(头歌实践教学平台习题)【合集】
有A、B、C三艘军舰同时开始鸣放礼炮各21响。已知A舰每隔5秒1次,B舰每隔6秒放1次,C舰每隔7秒放1次。编程计算观众总共听到几次礼炮声。根据提示,在右侧编辑器Begin--End之间的区域内补充必要的代码。开始你的任务吧,祝你成功!
191 13
|
9月前
|
存储 安全 C语言
【C语言程序设计——选择结构程序设计】预测你的身高(头歌实践教学平台习题)【合集】
分支的语句,这可能不是预期的行为,这种现象被称为“case穿透”,在某些特定情况下可以利用这一特性来简化代码,但在大多数情况下,需要谨慎使用。编写一个程序,该程序需输入个人数据,进而预测其成年后的身高。根据提示,在右侧编辑器补充代码,计算并输出最终预测的身高。分支下的语句,提示用户输入无效。常量的值必须是唯一的,且在同一个。语句的作用至关重要,如果遗漏。开始你的任务吧,祝你成功!,程序将会继续执行下一个。常量都不匹配,就会执行。来确保程序的正确性。
272 10
|
9月前
|
小程序 C语言
【C语言程序设计——基础】顺序结构程序设计(头歌实践教学平台习题)【合集】
目录 任务描述 相关知识 编程要求 测试说明 我的通关代码: 测试结果: 任务描述 相关知识 编程编写一个程序,从键盘输入3个变量的值,例如a=5,b=6,c=7,然后将3个变量的值进行交换,使得a=6,b=7,c=5。面积=sqrt(s(s−a)(s−b)(s−c)),s=(a+b+c)/2。使用输入函数获取半径,格式指示符与数据类型一致,实验一下,不一致会如何。根据提示,在右侧编辑器补充代码,计算并输出圆的周长和面积。
209 10
|
9月前
|
存储 编译器 C语言
【C语言程序设计——函数】分数数列求和2(头歌实践教学平台习题)【合集】
函数首部:按照 C 语言语法,函数的定义首部表明这是一个自定义函数,函数名为fun,它接收一个整型参数n,用于指定要求阶乘的那个数,并且函数的返回值类型为float(在实际中如果阶乘结果数值较大,用float可能会有精度损失,也可以考虑使用double等更合适的数据类型,这里以float为例)。例如:// 函数体代码将放在这里函数体内部变量定义:在函数体中,首先需要定义一些变量来辅助完成阶乘的计算。比如需要定义一个变量(通常为float或double类型,这里假设用float。
222 3
|
9月前
|
存储 C语言
【C语言程序设计——循环程序设计】利用数列的累加和求 sinx(头歌实践教学平台习题)【合集】
项的累加和,一般会使用循环结构,在每次循环中计算出当前项的值(可能基于通项公式或者递推关系),然后累加到一个用于存储累加和的变量中。在C语言中推导数列中的某一项,通常需要依据数列给定的通项公式或者前后项之间的递推关系来实现。例如,对于一个简单的等差数列,其通项公式为。的级数,其每一项之间存在特定的递推关系(后项的分子是其前项的分子乘上。,计算sinx的值,直到最后一项的绝对值小于。为项数),就可以通过代码来计算出指定项的值。对于更复杂的数列,像题目中涉及的用于近似计算。开始你的任务吧,祝你成功!
228 6