【1】string函数族
1. strlen
头文件:#include <string.h>
格式:size_t strlen(const char *s);
功能:计算字符串实际长度,不包括\0
参数:s:目标字符串首地址
返回值:字符串实际长度
2. strcpy
头文件 : #include <string.h>
格式:char *strcpy(char *dest, const char *src);
功能:实现字符串的复制
参数:dest:目标字符串的地址
src:源字符串的地址
返回值:目标字符串的地址
注意:字符串的结束字符'\0',也会一起拷贝。
3.strncpy
头文件: #include <string.h>
格式:char *strncpy(char *dest, const char *src, size_t n);
功能:实现前 n 个字符串的复制
参数:dest:目标字符串的地址
src:源字符串的地址
n:个数
返回值:目标字符串的地址
注意:字符串的结束字符'\0',也会一起拷贝。
4.strcat
头文件:#include <string.h>
格式:char *strcat(char *dest, const char *src);
功能:实现字符串的拼接
参数:dest:目标字符串的地址
src:源字符串的地址
返回值:目标字符串的地址注意:目标字符串'\0'被删除,然后连接源串
5.strncat
头文件:#include <string.h>
格式:char *strncat(char *dest, const char *src, size_t n);
功能:实现字符串的拼接
参数:dest:目标字符串的地址
src:源字符串的地址
n:指定要拼接字符的个数
返回值:目标字符串的地址
注意:目标字符串'\0'被删除,然后连接源串
6.strcmp
头文件:#include <string.h>
格式:int strcmp(const char *s1, const char *s2);
功能:用于字符串大小的比较
参数:s1,s2:用来比较的字符串的地址
返回值:ascii码值比较 两者相等 继续向后比较 如果不相等 返回s1-s2比较字符的ASCII值(从第一个字符开始比较)
>0 s1>s2
0 s1=s2
<0 s1<s2
7.strncmp
格式:int strncmp(const char *s1, const char *s2, size_t n);
功能:比较前n个字符的大小
练习:
void fun(char *p) //p=NULL
{
p = (char *)malloc(32);
strcpy(p, "hello");
}
int main()
{
char *m = NULL;
fun(m);
printf("%s\n", m); //NULL
return 0;
}
输出结果:段错误
子函数里面的 p 指针所指向的地址开辟的32 个字节的堆区空间,但是未释放,函数就结束了,内存泄漏导致段错误;主函数中的输出语句输出空指针的值,调用空指针,也会导致段错误;
解决方法:
(1)通过返回值
char *fun(char *p) //p=NULL
{
p = (char *)malloc(32);
strcpy(p, "hello");
return p;
}
int main()
{
char *m = NULL;
m = fun(m);
printf("%s\n", m); //hello
free(m);
m = NULL;
return 0;
}
(2)传参数的地址过去,通过二级指针
char *fun(char **p) //p=NULL
{
*p = (char *)malloc(32);
strcpy(*p, "hello");
}
int main()
{
char *m = NULL;
m = fun(&m);
printf("%s\n", m); //hello
free(m);
m = NULL;
return 0;
}
【2】递归函数
定义:自己调用自己的函数
执行过程:
(1)递推阶段:从原问题出发,按照递归公式递推,从未知推到已知,最终达到递归终止条件
(2)回归阶段:按照递归终止条件求出结果,逐步带入递归公式,回到原问题
例子:实现阶乘
int fun(int n){
if(n == 1){
return 1;
}
return n * fun(n - 1);
}
int main()
{
printf("%d\n",fun(5));
return 0;
}
【3】结构体
定义:用户自定义的数据类型,在结构体中可以包含若干不同数据类型的成员变量(也可以相同),是这些数据项目组合起来反应某一信息。
格式:
struct 结构体名 { 数据类型 成员变量名1; 数据类型 成员变量名2; 数据类型 成员变量名3; ..... };
注意:要在结构体定义的大括号后加分号 ‘ ; ’
1》结构体变量
概念:使用结构体类型定义的变量
格式:
struct 结构体名 变量名;
定义方式:
(1)定义结构体同时定义结构体变量
struct 结构体名
{
成员列表;
} 变量名;
(2)先定义结构体,后再定义结构体变量
struct 结构体名
{
成员列表;
};
struct 结构体名 结构体变量名;
(3)定义结构体时没有名称(缺省结构体类型名)
struct
{
成员列表;
} 变量名;
赋值:
(1) 在定义变量时,直接用大括号进行赋值
struct student
{
int age;
float score;
char name[32];
};
struct student stu1 = {23, 99, "zhangsan"};
struct student stu2 = {60, 61, "lisi"};
(2)定义变量时未初始化,然后通过结构体成员变量单独赋值
#include <stdio.h>
#include <string.h>
struct student
{
int age;
float score;
char name[32];
};
struct student stu1;
int main(int argc, char const *argv[])
{
stu1.age = 18;
stu1.score = 63;
strcpy(stu1.name, "zhangsan"); //数组类型不能直接赋值,需要通过strcpy函数进行赋值
return 0;
}
(3)点等法赋值
struct student
{
int age;
float score;
char name[32];
};
struct student stu1 =
{
.age = 18;
.score = 36.2;
};
访问:
输出:通过点的方式:结构体变量名 . 成员变量名
输入:结构体变量名 . 成员变量名
struct student
{
int age;
float score;
char name[32];
};
int main(){
struct student stu1;
scanf("%s",stu1.name);
printf("%s\n",stu1.name);
return 0;
}
2》重定义typedef
格式:typedef 旧名称 新名称
例:Typedef int * intp 则int * p就等同于intp p
定义格式:
(1)定义结构体同时重定义
typedef struct student { int age; float score; char name[32]; }stu; //这就将student结构体重定义为了stu,之后创建结构体变量就可以使用stu创建,更加简便
(2)先定义结构体,之后再重定义
struct student { int age; float score; char name[32]; }; type struct student stu; stu stu1;
3》结构体数组
概念:结构体类型相同的变量组成的数组
定义格式:
(1)定义结构体同时定义结构体数组
struct student { int age; float score; char name[32]; }stu[32]; //同时定义
(2)先定义结构体,再定义结构体数组
struct student { int age; float score; char name[32]; }; struct student stu[32];
初始化:
(1)定义的同时赋值
struct student { int age; float score; char name[32]; }stu[32] = { {20,99.9,liuhuan}, {23,34.4,lkjh}, {22,23.3,ksldfm}, ...... };
(2)先定义后再对每一个元素赋值
struct student { int age; float score; char name[32]; }stu[32]; strcpy(stu[0].name,"kkk"); stu[0].age = 20; stu[0].score = 34.4;
结构体数组的大小:
(1)结构体大小 * 元素个数
(2)sizeof(结构体数组名称)
结构体大小:
字节对齐原则 (64位系统)对齐 8 字节,比8字节小的就按照8字节开辟空间
#include <stdio.h> #include <stdlib.h> #include <string.h> struct demo { short a;// 2 开辟8字节 int b; //4 double c;//8 开辟8字节 }; int main() { struct demo Darr[3]; printf("%d\n", sizeof(struct demo)); // 16 return 0; }
4》结构体指针
概念:指向结构体变量的指针
定义格式:
struct 结构体名 * 指针名
struct demo
{
short a;
int b;
double c;
} d1, d2;
struct work
{
int a;
} w1;
int main()
{
struct demo *p = &d1;
struct demo *p1 = &w1;//错,不同类型的结构体不能混合指向
return 0;
}
赋值:
(1)指针变量名 ->成员变量名 = 新值
struct student *p = &stu1; p->age = 20; p->score = 23.4; printf("%d\n",p->age);
(2)(*p).成员变量
struct student *p = &stu1; (*p).age = 20; printf("%d\n",(*p).age);
指针大小:8字节 仍然是取决于计算机操作系统的大小
重定义指针:
struct student
{
int age;
float score;
char name[32];
}stu,*stup; //重定义了结构体和结构体指针
int main(){
stu stu1; //定义结构体变量
stup p = &stu1; //定义结构体指针
return 0;
}
总结:
1. 不能把结构体类型变量作为整体引用,只能对结构体类型变量中的各个成员变量分别引用
即:stu.id可以输出 直接输出stu不行 stu整体不行必须具体到每一个成员变量
2.如果成员变量本身属于另一种结构体类型,用若干个成员运算符一级级找到最低级的成员变量
3. 可以把成员变量当成普通变量运算(++ --都可以)
4. 在数组中,数组之间是不能彼此赋值的,结构体变量可以相互赋值
【4】共用体
概念
不同类型的成员变量共用同一块地址空间 使用union
格式
union 共用体名
{
成员变量1;
成员变量2;
};
#include <stdio.h>
union 共用体名 变量名;
union val //定义一个共用体
{
int num;
char ch;
};
union val v; //定义共用体变量
int main(int argc, char const *argv[])
{
v.num = 10;
v.ch = 'a';
printf("%d",v.num); //97
return 0;
}
特性:
(1)共用体所有成员共用同一块地址空间
(2)赋值顺序一最后一次赋值为内存中的实际数据
(3)共用体的大小为数据类型的数据大小
但当存在数组类型时,也需要进行共用体对齐,以最大的数据类型所占字节数为比较标准
可以用来判断大小端
union hello
{
int a;
char b;
};
int main()
{
union hello h1;
h1.a=0x12345678;
printf("a=%#x\n",h1.b);// ox78 小端模式
return 0;
}
【5】枚举
定义
用户自定义的数据类型,可以用于声明一组常数
格式
enum 枚举名
{
value1 = 值;
value2 = 值;
value3 = 值;
value4 = 值;
.....
}
#include <stdio.h>
enum week
{
MON = 1,
TUE,
WED,
};
int main()
{
int n;
scanf("%d", &n);
switch (n)
{
case MON:
printf("%d\n", MON);
break;
case TUE:
printf("%d\n", TUE);
break;
...
}
}
未赋初值,第一个常数会默认为0,依次加一。未赋值的部分在前一个的基础上加1
【6】存储类型
static extern register(寄存器)
(1)static:修饰变量和函数
修饰变量:
1.变量存放的位置在全局区(静态区)a. 有初值存在.data区域
b. 没有初值存在.bss区域2.生命周期为整个程序
3.限制作用域:
修饰的是局部变量,和普通局部变量作用域没有区别,但是可以延长它的生命周期。
修饰全局变量,限制仅在本文件中使用4.只初始化一次,在未赋初值时为0
修饰函数:
static 修饰的函数只能在本文件中使用
(2)extern 外部引用
通过extern引用其他文件中的全局变量或函数
main.c
#include <stdio.h>
extern int n;
extern void fun(); //通过extern引用了test.c中的fun.c函数
int main()
{
printf("%d\n", n);
fun();
return 0;
}
test.c
#include <stdio.h>
int n = 10;
void fun()
{
printf("helloworld\n");
}