常用头文件

stdio.h标准输出输出头文件

#include<stdio.h>

prinft()//标准输出语句

printf("直接字符串输出");

float a =1.2789;
printf("占位符输出 保留两位小数%.2f",a);  //1.28

scanf()//标准输入语句

int a,b;
printf("请输入两个数\你");
scanf(" %d %d",&a,&b);
printf("输入的数 a=%d\n输入的数 b=%d",a,b);  
/*
  输入的数 a=1
  输入的数 b=2
*/

putchar(c)//输出单独字符

getchar() //获取单个字符

char a,b;
prinft("请输入两个个字符\你");
a = getchar();
b = getchar();
getchar();
putchar(a);
putchar(b);

math.h C语言数学库

#include<math.h>

常用函数:

sqrt(x) //开平方

double a = sqrt(16); 
printf("%.2lf",a); //4.00

pow(2,3) //次方根 二的三次方

double b = pow(2,3);
printf("%.2lf",b);//2.00

round(3.145) //四舍五入

double c = round(3.145);
printf("%.2lf",c);//3.00

double c1 = round(3.545);
printf("%.2lf",c);//4.00

abs(-1); //整数绝对值

int a = abs(-1);
printf("%d",a); // 1

fabs(-1.258); //浮点数绝对值

double d = fabs(-1.258);
printf("%.3lf",d); //1.258

floor(1.258); //向下取整

double e = floor(1.258);
printf("%.3lf",e); //1.000

ceil(1.258); //向上取整

double f = ceil(1.258);
printf("%.3f",f);//2.000

常量PI M_PI

printf("%lf",M_PI);

stdlib.h C语言标准库

#include<stdlib.h>

malloc():动态分配内存

int* arr = (int*)malloc(4 * sizeof(int));  //分配四个 int 单位的内存
free(arr);

calloc():分配已清零的内存

realloc():调整已分配内存大小

free():释放动态内存(防止内存泄露)

string.h 字符

#include <string.h>

选择控制结构:

if 单分支语句

int age = 0;
scanf(" %d",&age);
if(age <18)
{
   printf("未成年");
}

if-else if双分支语句

int age = 0;
scanf(" %d",&age);
if(age<18)
{
   printf("未成年");
}
else
{
   printf("成年人");
}

if-else-if-else if多分支语句

int age = 0;
scanf(" %d",&age);
if(age>=70)
{
   printf("老年人");
}else if(age>=40)
{
   printf("中年人");
}else if(age>=18)
{
   printf("年轻人");
}else{
   printf("未成年");
}

switch多分支语句

数字控制案例

int selector = 1;
while(selector != 0){
    printf("欢迎使用本系统,请输入操作指令续序号:\n 1:添加用户\n 2:删除用户 \n 0:退出系统\n");
    scanf(" %d",&selector);
    switch(selector){
       case 1:
             printf("已执行添加用户\n");
             break;
       case 2:
             printf("已执行删除用户\n");
             break;
       case 0:
             printf("感谢使用!下次见\n");
             break;
       default:
             printf("操作指令错误,请重新输入\n");
    }
}

字符控制案例

char selector = 'a';
while(selector != 'q'){
    printf("欢迎使用本系统,请输入操作指令续序号:\n a:添加用户\n b:删除用户 \n q:退出系统\n");
    selector = getchar();
    while(getchar() != '\n');
    switch(selector){
         case 'a':
               printf("已执行 添加用户!\n");
               break;
         case 'b':
               printf("已执行 删除用户\n");
               break;
         case 'q':
               printf("感谢使用,下次见!\n");
               break;
         default:
               printf("指令输入有误,请重新输入\n");          
    }
}

循环控制语句

for循环 满足条件才循环

for(int i = 1;i<=5;i++){
   printf("第%d次",i);
}

continue

结束本次循环(跳过 continue 后面的代码进入下一轮循环【如果有】)

for(int i =0;i<=5;i++){
    if(i == 3){
       continue;
     }
     printf("%d",i);//0,1,2,4,5
}

break

终止循环
for(int i =0;i<=5;i++){

if(i == 3){
      break;
}
printf("%d\n",i); //0,1,2

}

while循环 满足条件才循环

int counter = 1;
while(counter<=5){
   printf("第%d次",counter); //1,2,3,4,5
   counter++;
}

do-while循环 不关条件是否满足,先执行一次循环 - 满足条件才循环

int counter = 1;
do{
    printf("第 %d 次",counter); //1,2,3,4,5
    counter++;
}while(counter<=5);

注意:不要忘记 do-while 后的分号!

函数

函数的定义

无返回值函数

void sayHello(){
    printf("hello\n");
}

带返回值函数

int add(int a,int b){
    int sum = a+b;
    return sum;
}

递归函数

栈的概念
入栈push -> 出栈pop
先入后出
例子:累加和
求 1-num 的累加和

int sum(int num){
   if(num == 1){
         return 1; //程序出口 退出条件 
   }
   return num + sum(num-1); //自己调用自己
}

指针:

指向内存地址

间接寻址运算符 *

根据地址找到里面存的

取地址运算符 &

拿到某变量在内存的地址

int a = 20;
int *p = &a;  //此处*表示声明指针

*定义是是表示声明指针 使用时表示间接寻址(即取地址存储的值)

//以下都是一样的意思 (都是修改 a 的值为 10)

a = 10;
printf("%d\n",a); // 10
*p = 10;
printf("%d\n",a); // 10

交换变量例子


全局变量:放置在所有函数的外侧最上方 程序运行结束才销毁
局部变量:放置在单独函数内部包括 main 函数 随之函数运行完成结束而销毁,仅在函数内部可使用


注意 :函数要先声明方可使用,程序是顺序执行 必须先在程序最顶部定义,程序运行时根据顺序执行先读入自定义函数到内存。才可以被主函数查找并调用!

#include <stdio.h>

// 1. 函数声明(写在最顶部!) 或者直接在这里定义好相关的功能
void swap(int *a, int *b);

int main() {
    swap(&a, &b);  // 2. main 调用,能找到!
    return 0;
}

// 3. 函数定义(可以放在 main 后面!)
void swap(int *a, int *b) {
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

交换变量函数:
放到主函数的外面的上面

void swap(int *a,int *b){
    int temp;
    temp = *a;
    *a = *b;
    *b = temp;
}

主函数内:

int a =0;
int b =0;

scanf(" %d %d",&a,&b);

printf("未交换前的 a=%d;b=%d\n",a,b);

swap(&a,&b);
printf("交换后的 a=%d,b=%d\n",a,b);

指针数组

int a=10,b=20,c=30;
//定义指针数组 存储数的指针地址
int *arr[] = {&a,&b,&c};
//使用间接寻址操作符*  取对应数组索引下指针地址的值
printf("%d\n%d\n%d",*arr[0],*arr[1],*arr[2]); //10 20 30

函数指针

//普通函数
int add(int a,int b){
    return a+b;
}
//函数指针
int (*add_ptr)(int,int) = add;

//以下写法代表的是一样的执行
printf("%d\n",add(1,2));
printf("%d\n",add_ptr(1,2));

函数指针的应用

回调函数
//mian(外部)函数上面
double calc(double a,double b,double (*func)(double,double)) //double(*func)(double,double)代表一个名为 func 的函数指针
{
    return func(a,b);//返回 func 函数的处理结果
}

double div1(double a,double b){
    return a/b;
}
double add(double a,double b){
    return a+b;
}

//main 函数内
double a = 0.0;
double b = 0.0;
double res = 0.0;
char operation = ' '; //注意字符不能为空 此处使用空格初始化

printf("请输入两个数:\n");
scanf(" %lf %lf",&a,&b);

printf("请输入进行的运算:\n + \n /\n");
scanf(" %c",&operation);

if(operation == '+'){
    res = calc(a,b,add); //使用+运算函数处理
    printf("%lf",res);
}else if(operation == '/'){
    res = calc(a,b,div1); //使用/运算函数处理
    printf("%lf",res);
}else{
    printf("不支持的操作");
}


动态内存 malloc + 字符指针

固定数组大小

char str[20];

动态分配

char *str_ptr = (char*)malloc(20 * sizeof(char));// 开辟 20 个字符长度的 str 指针
char *str1_ptr = (char*)malloc(20);

判断是否申请成功

if(str_ptr == NULL){
   return -1;
}

使用:

strcpy(str_ptr,"hello 小胡");
printf("%s",str_ptr);

数组

一维数组

数组的定义

int arr[]={1,2,3,4,5}

数组访问
数组索引 0(第一个元素)设置为 100

arr[0] = 100;

数组指针 指向数组第一个元素(索引 0)的地址

int *arr_ptr = arr;

向函数传递一维数组

void func1(int arr[],int len){};

指针写法

void func2(int *arr,int len){};

带数组大小

void func3(int arr[5]){};

基于数组的常用算法和应用

1.遍历数组
int arr[] = {1,2,3,4,5};
int len =5;
for(int i =0;i<len;i++){
    printf("%d",arr[i]);
}
2.求数组最大值
int arr[] = {1,2,3,4,5};
int max = arr[0];//设置第一位为默认最大值
for(int i =0;i<5;i++){
   //如果当前索引下的数大于默认值 就把他设置为最大值
   if(arr[i]>max){
       max = arr[i];
    }
}
3.求数组最小值
int arr[] = {1,2,3,4,5};
int min = arr[0];//设置第一位为默认最小值
for(int i=0;i<5;i++){
     //如果当前索引下的数小鱼默认值 就把他设置为最小值
     if(arr[i]<min){
         min = arr[i];
     }
}
4. 数组求和
int arr[] = {1,2,3,4,5};
int sum = 0;
for(int i =0;i<5;i++){
    sum+=arr[i];
}
5.数组反序
int arr[] = {1,2,3,4,5};
int len = 5;
//仅需要循环一半
for(int i =0;i<len/2;i++){
    //交换变量 最左边的交换到最右边
    int temp = arr[i]; 
    //最右边即 数组长度-1(因为下标从0开始)-i(减去当前下标 可算出跟右侧下标为几的元素交换)
    //即 len-1-i 就是右边要交换的元素索引
    arr[i] = arr[len-1-i];   
    arr[len-1-i] = temp; 
}
6.查找元素
int arr[] = {1,2,3,4,5};
int len = sizeof(arr)/siziof(int);
int target = 4;
for(int i = 0;i<len;i++){
    if(arr[i] == target){
         printf("找到啦 你要找的数字%d 的target,位于索引%d",target,i);
    }
}
7.冒泡排序

升序版:

int arr[] = {2,1,4,9,3};
int len = sizeof(arr)/sizeof(int);

升序:从小到大排  (升:越来越大)
降序:从大到小排  (降:越来越小)

//无需进行最后一次比较(最后一位会自己排好) 故len-1

for(int i = 0 ;i<len-1;i++)
{
    //每次都将本索引位置的元素 跟其他几位索引的元素进行比较
    //减去当前索引 i 的位置可以算出需要剩余比较的次数(每一轮少比 i 次)
    for(int j = 0;j<len-i-1;j++){
         //两两比较 大的后移
         if(arr[j]>arr[j+1]){
             //交换 arr[j]和 arr[j+1]
             int temp = arr[j];
             arr[j] = arr[j+1];
             arr[j+1] = temp;
             
         }
    }
}
//输出验证
for(int i = 0;i<len;i++){
    printf("%d \t",arr[i]);
}

降序版:

int arr[] = {2,1,6,7,9,8};
int len = sizeof(arr)/sizeof(int);
for(int i = 0;i<len-1;i++){
    for(int j = 0;j<len - i -1;j++){
        //两两比较小的放后面 
        // 比较条件  j+1>j   j+1 大 j小     j+1 和 j 互换位置
        //升序降序仅和 if 的条件判断有关!
        if(arr[j+1]>arr[j]){
             int temp = arr[j+1];
             arr[j+1] = arr[j];
             arr[j] = temp;
        }
    }
}

//输出验证
for(int i = 0;i<len;i++){
    printf("%d \t",arr[i]);
}

二维数组

向函数传递二维数组

数组案例

输入输出数组

倒置数组

向函数传递一维数组

c语言字符串

字符串定义与使用

常用的字符串函数

常用排序算法(数组)

一维数组插入 删除 查找

冒泡排序

选择排序

结构体

结构体基本结构定义

struct Student{
    char name[20];
    int age;
    float score;
};

创建结构体实例

struct Student stu; //创建名为 stu 的 Student 结构体

结构体赋值

1.逐个赋值:

strcpy(stu.name,"张三");
stu.age = 18;
stu.score = 99.5;

2.一次赋值

struct Student stu1 = {"Ethan",20,99.9};

访问结构体成员

printf("姓名:%s\n",stu.name);
printf("年龄:%d\n",stu.age);
printf("成绩:%f\n",stu.score);

printf("姓名:%s\n",stu1.name);
printf("年龄%d\n",stu1.age);
printf("成绩:%f\n",stu1.score);

指向结构体的指针

struct Student stu2; //创建 stu2 Student结构体实例
struct Student *stu_ptr = &stu2;  //创建 stu_ptr 结构体指针,并赋 stu2 结构体实例 地址给 stu_ptr

strcpy(stu_ptr->name,"小胡");
stu_ptr->age = 21;  //通过结构体指针设置 age
stu_ptr->score = 99.8;

printf("%s \t %d \t %f",stu2.name,stu2.age,stu2.score);

结构体指针的应用

1.通过函数修改结构体实例

普通函数变量传参 函数里面变了实际结构体实例为改变(拷贝)

void changeStu(struct Student *stu_ptr,char name[],int age,float score){

strcpy(stu_ptr->name,name);
stu_ptr->age = age;//修改的是实例的参数
stu_ptr->score = score;

}
int main() {

struct  Student stu; //创建stu结构体实例
struct Student *stu_ptr = &stu;

//调用 changeStu函数修改结构体实例

changeStu(stu_ptr,"小胡",19,99.6);
printf("%s\t %d\t %f",stu_ptr->name,stu_ptr->age,stu_ptr->score);

}

2.节省内存

复杂结构体传参
太大了 使用结构体指针仅需传一个地址


// 调用
changeStu(&stu);  // 传地址

否则
需要传入整个结构体

// 调用
changeStu(stu);
3.数据结构 链表,树

struct Node{

int data;
struct Node *next;

};

4.动态内存创建结构体

//创建 Student 结构体指针 stu_ptr 并将分配好的内存地址给到结构指针
struct Student stu_ptr = (struct Student )malloc(sizeof(struct Student));
if(stu_ptr == NULL){

printf("内存分配失败!");
return -1;

}

strcpy(stu_ptr->name,"小胡");
stu_ptr->age = 20;
stu_ptr->score = 90.0;

printf("%s\t %d \t %.2f",stu_ptr->name,stu_ptr->age,stu_ptr->score);

free(stu_ptr);//使用完成后释放内存
stu_ptr = NULL; //指针回空

结构体数组

结构体数组存储复杂数据对象,数据处理算法

单链表

动态分配单链表

单链表的定义

单链表的插入

单链表的遍历

单链表的删除

单链表的查找

常见查找算法

顺序查找

二分查找

常考代码例子:

99 乘法表

斐波那契数列

阶乘

最大最小值

最后修改:2026 年 03 月 19 日
如果觉得我的文章对你有用,请随意赞赏