能力有限,其他内容正在路上。。。
1.数据类型
常量:程序运行时其值不能改变的量(即常数)
1.1变量:
程序运行时其值可以被改变的量
语法: 数据类型 变量名称=变量的值;
#include <stdio.h>
int main(){
int a;
a=10;
printf("a=%d\n",a);
a=20;
printf("a=%d\n",a);
}
1.2常量:
用于记录程序中不可更改的数据
C
语言中的常量大概有以下五种表现形式
1.
数值常量
(
整数型常量(整数) 、实数型常量(小数)
)
2.
字符常量
'a' 'b' 'c' '\n' '\t'
3.
字符串常量
"hello world"
4.
#define
宏常量:
#define
常量名 常量值
5.
const
修饰的变量
const
数据类型 常量名
= 常量值
通常在变量定义前加关键字const,修饰该变量为常量,不可修改
#include <stdio.h>
void test01()
{
//一共有5种表现的形式
//1、数值常量(整数型常量(整数) 、实数型常量(小数))
// 100 200 300 3.14 1.1 2.2 3.3
//100 = 200; //error 常量是不可以修改的!
//2、字符常量 'a' 'b' 'c' '\n' '\t'
//'a' = 'b'; error
//3、字符串常量 "hello world"
//"hello world" = "aaaa"; error
//4、符号常量 (宏常量)
//利用 #define
//printf("一周一共有%d天\n", DAY);
//DAY = 14; error
//5、const 修饰的变量
const int month = 12;
printf("一年一共有%d月\n", month);
//month = 24; error 此时是一个常量了 不可以修改
}
main(){
test01();
}
1.3关键字
作用:
关键字是
C
中预先保留的单词(标识符)
在定义变量或者常量时候,不要用关键字
1.4 标识符命名规则
作用
:
C++
规定给标识符(变量、常量)命名时,有一套自己的规则
- 标识符不能是关键字
- 标识符只能由字母、数字、下划线组成
- 第一个字符必须为字母或下划线
- 标识符中字母区分大小写
建议:给标识符命名时,争取做到见名知意的效果,方便自己和他人的阅读
1.5整型
C
语言规定在创建一个变量或者常量时,必须要指定出相应的数据类型,否则无法给变量分配内存
作用
:整型变量表示的是
整数类型
的数据
![](https://i-blog.csdnimg.cn/blog_migrate/d2900ea24d76b9df3f1045e23a00e766.png)
# include <stdio.h>
void test01()
{
short num1 = 32768; // - 32768 ~ 32767
int num2 = 32768; // 9 位数 到 10 位数之间
long num3 = 10;
long long num4 = 10;
printf("num1 = %hd\n", num1);
printf("num2 = %d\n", num2);
printf("num3 = %ld\n", num3);
printf("num4 = %lld\n", num4);
}
main(){
test01();
}
1.6sizeof关键字
作用:
利用
sizeof
关键字可以
统计数据类型所占内存大小
语法:
sizeof(
数据类型 |
变量
)
void test01()
{
printf("short占用内存空间为:%d\n", sizeof(short)); //2
int a = 10;
printf("a占用内存空间为: %d\n", sizeof(a)); //4
printf("int 占用内存空间为: %d\n", sizeof(int)); //4
printf("long 占用内存空间为: %d\n", sizeof(long)); //4
printf("long long 占用内存空间为: %d\n", sizeof(long long)); // 8
}
1.7字符型
作用:
字符型变量用于显示单个字符
语法:
char ch = 'a'
;
注意1:在显示字符型变量时,用单引号将字符括起来,不要用双引号注意2:单引号内只能有一个字符,不可以是字符串C 语言中字符型变量只占用 1 个字节 。字符型变量并不是把字符本身放到内存中存储,而是将对应的 ASCII 编码放入到存储单元
![](https://i-blog.csdnimg.cn/blog_migrate/6140189644603bb352720d02db1c1fbb.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c39440e4020253254a0eb4d6f1b89e10.png)
ASCII 码大致由以下 两部分组 成:ASCII 非打印控制字符: ASCII 表上的数字 0-31 分配给了控制字符,用于控制像打印机等一些外围设备。ASCII 打印字符:数字 32-126 分配给了能在键盘上找到的字符,当查看或打印文档时就会出现。
void test01()
{
char a = 'a';
printf("%c\n", a);
printf("%d\n", sizeof(char)); //1
a = 'b';
printf("%c\n", a);
//a = "c"; //error
//a = 'abcdefg'; //error
//整形
printf("%d\n", a);
// A - 65 a - 97 0 - 48
}
1.8浮点型
作用
:用于
表示小数
浮点型变量分为两种:1. 单精度 float2. 双精度 double两者的 区别 在于表示的有效数字范围不同。
//浮点型 常量
void test01()
{
printf("sizeof = %d\n", sizeof(3.14)); //默认认为小数是double数据类型
printf("sizeof = %d\n", sizeof(3.14f)); //加入f后 变为float数据类型
}
//浮点型 变量
void test02()
{
float a = 1.111f;
printf("%f\n", a); //默认显示小数点后6位
printf("%.2f\n", a); //显示两位小数
double b = 2.222;
printf("%lf\n", b);
printf("%.3lf\n", b);
float PI = 3.141592653589793;
printf("%.10f\n", PI);
double PI2 = 3.141592653589793;
printf("%.10lf\n", PI2);}
1.9字符串
作用:用于表示一串字符
//字符串常量
void test01()
{
//双引号引起的内容 称为字符串常量
printf("%s\n", "hello world"); // 双引号引起的内容中会带着字符串结束标志 \0
注意:字符串要用双引号括起来
示例:
//双引号会返回字符串的首字符的地址编号
//%s输出时 遇到\0 结束输出
printf("sizeof = %d\n", sizeof("hello world"));
printf("%s\n", "hello\0world");
printf("%s\n", "\0hello world");
}
//字符串变量
void test02()
{
char str[] = "hello world";
printf("%s\n", str);
printf("sizeof = %d\n", sizeof(str));//12 hello 空格 world \0
str[0] = 'x';
printf("%s\n", str);
}
1.10数据的输入
作用:用于从键盘获取数据语法:scanf("格式化占位符",输入数据地址);
#include <stdio.h>
//整型
void test01(){
int a;
//scanf(格式化内容,输入数据的地址)
//scanf有阻塞行为,等待用户的输入
scanf("%d",&a);
printf("%d",a);
}
//浮点型
void test02(){
double a;
float b;
scanf("%lf,%f",&a,&b);// 输入时 double 只能用%lf float 只能用%f
printf("%.2lf,%.2lf",a,b);//输出时都可
}
//字符串
void test03(){
char ar[]="";
scanf("%s",ar);// 遇到空格结束
printf("%s",ar);
}
//字符型
void test04(){
char a;
scanf("%c",&a);
printf("%c",a);
}
void test05()
{
int num = 0;
printf("请重新给num赋值\n");
scanf("%d", &num); //\n
printf("num = %d\n", num);
char ch1;
ch1 =getchar();//从缓冲区中获取一个字符
char ch = 'a';
printf("请重新给ch赋值\n");
scanf("%c", &ch);
printf("ch = %c\n", ch);
putchar('a'); //向屏幕中打印1个字符
}
main(){
test05();
}
2.运算符
作用:
用于执行代码的运算
![](https://i-blog.csdnimg.cn/blog_migrate/8691fa6db8b027e3149db90b25d11635.png)
2.1算术运算符
作用:用于处理四则运算
//算术运算符 + - * /
void test01()
{
int a = 10;
int b = 3;
printf("a + b = %d\n", a + b); //13
printf("a - b = %d\n", a - b); //7
printf("a * b = %d\n", a * b); //30
printf("a / b = %d\n", a / b); //3 两个正数相除 结果也是正数,小数部分舍弃掉
int a2 = 10;
int b2 = 20;
printf("a2 / b2 = %d\n", a2 / b2); // 0
int a3 = 10;
int b3 = 0;
//printf("a3 / b3 = %d\n", a3 / b3);//error 除数不可以为0
//两个小数之间 是可以做除法运算的
double d1 = 0.5;
double d2 = 0.25;
printf("d1 / d2 = %lf\n", d1 / d2);
// 两数相除 只要有一个数是 浮点型 结果就为浮点型
}
总结:在除法运算中,除数不能为0
//取模 取余 运算
void test02()
{
int a1 = 10;
int b1 = 3;
printf("10 %% 3 = %d\n", a1 % b1);
int a2 = 10;
int b2 = 20;
printf("a2 %% b2 = %d\n", a2 % b2); // 10
int a3 = 10;
int b3 = 0;
//printf("a3 %% b3 = %d\n", a3 % b3); //error
double d1 = 5.3;
double d2 = 1.1;
//对于小数而言,是不可以取余数
//printf("d1 %% d2 = %lf\n", d1 %d2);//error
}
总结:只有整型变量可以进行取模运算
void test04()
{
//后置递增
int a = 10;
a++; // a = a + 1;
printf("a = %d\n", a);
//前置递增
int b = 10;
++b; // b = b+1;
示例:
printf("b = %d\n", b);
//作为独立语句,前置和后置没有区别
//当进行混合运算时,才有区别
//前置++ 先对变量 进行 ++ 再 计算表达式
int a3 = 10;
int b3 = ++a3 * 10; // a3 = a3 + 1 b3 = a3 * 10
printf("a3 = %d\n", a3); //11
printf("b3 = %d\n", b3); //110
//后置++ 先计算表达式 再对变量进行++运算
int a4 = 10;
int b4 = a4++ * 10;
printf("a4 = %d\n", a4); //11
printf("b4 = %d\n", b4); //100
}
总结:前置递增先对变量进行++,再计算表达式,后置递增相反
2.2赋值运算符
作用:
用于将表达式的值赋给变量
![](https://i-blog.csdnimg.cn/blog_migrate/76d58c9d814bc855975ca443723f0df9.png)
void test01()
{
//赋值 运算 将=右边的值 赋给=左边
int a = 10;
a = 100;
int b = a;
b = a;
//左值 能够在=左边的值 成为左值
//右值 只能在=右边的值 成为右值
// +=
a = 10;
a += 2; // a = a + 2;
printf("a = %d\n", a); // 12
// -=
a = 10;
a -= 2; // a = a - 2;
printf("a = %d\n", a); //8
// *=
a = 10;
a *= 2; // a = a * 2;
printf("a = %d\n", a); // 20
// /=
a = 10;
a /= 2; // a = a / 2;
printf("a = %d\n", a); // 5
// %=
a = 10;
a %= 2; // a = a % 2;
printf("a = %d\n", a); // 0
}
void test02()
{
//注意事项:在做+= -= *=....中 =右边的表达式要看成一个整体
int num = 10;
num *= 3 + 5; // num = num * (3 + 5)
printf("num = %d\n", num); // 80
}
2.3 比较运算符
用于表达式的比较,并返回一个真值或假值
void test01()
{
int a = 10;
int b = 20;
//在C中 0 代表假 非零 代表真
printf("a==b %d\n", a == b); //0
printf("a!=b %d\n", a != b); //1
printf("a>b %d\n", a > b); //0
printf("a<b %d\n", a < b); //1
printf("a>=b %d\n", a >= b); //0
printf("a<=b %d\n", a <= b); //1
}
注意:C语言的比较运算中, “真”用数字“1”来表示, “假”用数字“0”来表示
2.3逻辑运算符
作用:
用于根据表达式的值返回真值或假值
![](https://i-blog.csdnimg.cn/blog_migrate/ea6abf0c90524f913831705bb73eecaf.png)
//逻辑非 !
void test01()
{
int a = 10;
printf("!a = %d\n", !a); //0
printf("!!a = %d\n", !!a); //1
printf("%d\n", !100); // 0
printf("%d\n", !!100); // 1
printf("%d\n", !- 100); // 0
//非零都是真!!!
}
//逻辑与
void test02()
{
//同真为真 一假为假
int a = 10;
int b = 20;
printf(" a && b = %d\n", a && b); //1
a = 10;
b = 0;
printf(" a && b = %d\n", a && b); //0
a = 0;
b = 0;
printf(" a && b = %d\n", a && b); //0
//注意:只有表达式1 为真 ,才会判断表达式2 短路特性
4 < 3 && printf("hello1\n");
4 > 3 && printf("hello2\n");
}
//或
void test03()
{
// 同假为假 一真为真 ||
int a = 10;
int b = 10;
printf("a || b = %d\n", a || b); // 1
a = 0;
b = 10;
printf("a || b = %d\n", a || b); // 1
a = 0;
b = 0;
printf("a || b = %d\n", a || b); // 0
//注意:只有表达式1为假 才判断表达式2 短路特性
4 < 3 || printf("hello1\n"); //执行hello1
4 > 3 || printf("hello2\n"); //不执行 hello2
}
非运算 总结: 真变假,假变真
与运输 总结:逻辑与运算符总结: 同真为真,其余为假
逻辑 或 运算符总结: 同假为假,其余为真
3.5运算符优先级
在一些表达式中,可能会出现多个运算符同时出现,此时运算符的优先级尤为重要
5.数组
5.1概述
所谓数组,就是一个集合,里面存放了相同类型的数据元素
- 特点1:数组中的每个数据元素都是相同的数据类型
- 特点2:数组是由连续的内存位置组成的
5.2一维数组
5.2.1一维数组的定义方式
1. 数据类型 数组名 [ 数组长度 ] ;2. 数据类型 数组名 [ 数组长度 ] = { 值 1 ,值 2 ...} ;3. 数据类型 数组名 [ ] = { 值 1 ,值 2 ...} ;
# include <stdio.h>
void test01()
{
//定义方式1
//数据类型 数组名 [元素个数];
//初始的数据是随机
int score[10]; // 数组名 score , 数组中存放最多10个数据,每个数据的数据类型
//给数组元素赋值
//从0开始索引位置
score[0] = 100;
score[1] = 99;
score[2] = 98;
//score[10] = 100; //下标越界
//利用下标法输出
printf("%d\n", score[0]);
printf("%d\n", score[1]);
printf("%d\n", score[2]);
//定义方式2
//数据类型 数组名 [元素个数] = {值1,值2 ,值3 ...}
int score2[10] = { 0,1, 2, 3, 4, 5, 6, 7, 8, 9 };
//int score2[10] = { 0, 1, 2, 3, 4, 5}; //不足的10个数据,剩余的位置用0填充
//int score2[10] = { [1] = 10 , [5] = 50 , [7] = 70}; //部分初始化
for (int i = 0; i < 10; i++)
{
printf("%d\n", score2[i]);
}
//定义方式3
//数据类型 数组名[] = {值1,值2 ,值3 ...}
int score3[] = { 1, 2, 3, 4, 5 ,6,7,8};
for (int i = 0; i < 8; i++)
{
printf("%d\n", score3[i]);
}
}
int main(){
test01();
}
总结
1
:
数组名的命名规范与变量名命名规范一致,不要和变量重名
总结
2
:
数组中下标是从0开始索引
5.2.2一维数组的数组名
一维数组名称的用途:
1. 可以统计整个数组在内存中的长度2. 可以获取数组在内存中的首地址
# include <stdio.h>
//一维数组名称
void test02()
{
int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
//1、统计整个数组占用内存空间大小
printf("sizeof arr = %d\n", sizeof(arr));
printf("每个数据占用空间大小 = %d\n", sizeof(arr[0]));
printf("数组中元素的个数 = %d\n", sizeof (arr) / sizeof(int));
//2、通过数组的名称,获取到数组的首地址
printf("数组的首地址为:%p\n", arr); //%p可以用十六进制显示 %d用十进制显示地址
//printf("数组的首地址为:%p\n", arr);
printf("数组中第一个元素的地址:%p\n", &arr[0]);
printf("数组中第二个元素的地址:%p\n", &arr[1]);
printf("数组中第三个元素的地址:%p\n", &arr[2]);
//数组名常量,不可以赋值
//arr = 100; error不可以给数组名赋值
}
int main(){
test02();
}
注意:数组名是常量,不可以赋值总结 1 :直接打印数组名,可以查看数组所占内存的首地址总结 2 :对数组名进行 sizeof ,可以获取整个数组占内存空间的大小
案列:
利用一个数组记录五只小猪的体重,手动输入五只小猪的体重,并打印最重的小猪体重
# include <stdio.h>
int main(){
int a[5]={};
int i,max,index;
//index=0;
max=0;
for (i=0;i<5;i++){
scanf("%d",&a[i]);
if (a[i]>max){
max=a[i];
index=i;
}
}
printf("%d,第%d只",max,index);
}
5.4.1字符数组的输入与输出
# include <stdio.h>
# include <string.h>
int main(){
void test1();
// test1();
void test2();
// test2();
void test4();
test4();
}
//字符串输入
// scanf 输入
void test1(){
//创建数组并初始化为空
//char arr[16]={};
char arr[16]="";
scanf("%s",arr);// 遇空格结束 输入 hello world 只会输出hello
printf("%s\n",arr);
//数组名常量 不能等号赋值
// arr="hello world "
strcpy(arr,"hello world");
printf("%s",arr);
}
// gets 不推荐
void test2(){
char arr[16]={};
gets(arr);//遇到换行符结束 ,可以输入空格
//不会检查数据是否溢出,一旦溢出,程序结束
printf(arr);
}
//fgets 推荐
void test3(){
char arr[16]={};
fgets(arr,sizeof(arr),stdin);//stdin 指标准输入 默认是键盘
printf(arr);
}
//字符串输出
void test4(){
char arr1[16]={"hello world"};
printf("%s",arr1);
puts(arr1);//自带换行
fputs(arr1,stdout); // stdout 标准输出 默认屏幕 不带换行
}
6.函数
作用:将一段经常使用的代码封装起来,减少重复代码
6.1 函数的定义
函数的定义一般主要有
5
个步骤:
1
、返回值类型
2
、函数名
3
、参数表列
4
、函数体语句
5
、
return
表达式
语法:
返回值类型 函数名 (参数列表){函数体语句return 表达式}
返回值类型 :一个函数可以返回一个值。在函数定义中函数名:给函数起个名称参数列表:使用该函数时,传入的数据函数体语句:花括号内的代码,函数内需要执行的语句return 表达式: 和返回值类型挂钩,函数执行完后,返回相应的数据
示列:定义一个加法函数,实现两个数相加
//函数定义
int add(int num1, int num2)
{
int sum = num1 + num2;
return sum;
}
6.2函数的调用
语法:
函数名(参数)
# include<stdio.h>
//函数定义
int add(int num1, int num2)//形式参数 num1 num2,没有实际的数据 只是形式上的参数
{
int sum = num1 + num2;
return sum;
}
int main(){
//add(10,20);//函数的调用 将参数传递给形参
printf("%d", add(10,20));
}
6.3函数的声明
作用:
告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。
函数的
声明可以多次
,但是函数的
定义只能有一次
# include<stdio.h>
//如果函数的定义在使用函数的上方 自动声明
//如果函数的定义在使用函数的下方 需要提前声明
int main(){
int add(int,int);//函数的声明
//add(10,20);//函数的调用 将参数传递给形参
printf("%d", add(10,20));
}
//函数定义
int add(int num1, int num2)//形式参数 num1 num2,没有实际的数据 只是形式上的参数
{
int sum = num1 + num2;
return sum;
}
6.4参数的常见样式
1.
无参无返
2.
有参无返
3.
无参有返
4.
有参有返
// 1、无参无返
void func1()
{
printf("this is func1\n");
}
// 2、有参无返
void func2(int a)
{
printf("this is func2 a = %d\n", a);
return; //可选添加
}
// 3、无参有返
int func3()
{
printf("this is func3\n");
return 1000;
}
// 4、有参有返 形参中的变量名 C语言下 必须写
int func4(int a)
{
printf("this is func4 a = %d\n", a);
return a;
}
void test01()
{
//1、无参无返
func1();
//2、 有参无返
func2(10);
//3、无参有返 返回值 可以在调用时候接受或者不接受
int num = func3();
printf("num = %d\n", num);
//4、有参有返
int num2 = func4(10000);
printf("num2 = %d\n", num2);}
6.5值传递
所谓值传递,就是函数调用时实参将数值传入给形参
值传递时,
如果形参发生,并不会影响实参
#include <stdio.h>
void swap(int num1, int num2)
{
printf("num1 = %d\n", num1);
printf("num2 = %d\n", num2);
int temp = num1;
num1 = num2;
num2 = temp;
printf("交换后:\n");
printf("num1 = %d\n", num1);
printf("num2 = %d\n", num2);
}
void test01()
{
int a = 10;
int b = 20;
swap(a, b);
printf("main中的a = %d\n", a);
printf("main中的b = %d\n", b);}
main(){
test01();
}
7.指针
指针的作用: 可以通过指针间接访问内存内存编号是从 0 开始记录的,一般用十六进制数字表示可以利用指针变量保存地址
7.1指针的定义和使用
指针变量定义语法:
数据类型
*
变量名;
#include <stdio.h>
int main(){
int a=10;
int *p;
p=&a;
printf("&a:%d\n",&a);
printf("p:%d\n",p);
printf("a:%d\n",a);
printf("*p:%d\n",*p);
}
指针变量和普通变量的区别普通变量存放的是数据 , 指针变量存放的是地址指针变量可以通过 " * " 操作符,操作指针变量指向的内存空间,这个过程称为 解引用
总结1: 我们可以通过 & 符号 获取变量的地址总结2:利用指针可以记录地址总结3:对指针变量解引用,可以操作指针指向的内存
7.2指针所占内存空间
#include <stdio.h>
int main(){
printf("sizeof int * = %d\n", sizeof(int *));
printf("sizeof char * = %d\n", sizeof(char *));
printf("sizeof float * = %d\n", sizeof(float *));
printf("sizeof double * = %d\n", sizeof(double *));
}
总结:所有指针类型在32位操作系统下是4个字节,
所有指针类型在64位操作系统下是8个字节
7.3 空指针和野指针
空指针 :指针变量指向内存中编号为 0 的空间用途: 初始化指针变量注意: 空指针指向的内存是不可以访问的
#include <stdio.h>
int main(){
int* p = NULL; //NULL本质就是 0
//访问空指针的存储内容 会报错
//内存地址编号为 0 ~ 255之间的系统占用的内存,用户不可以访问
printf("%d\n", *p); //error 空指针不可以访问
}
野指针:指针变量指向非法的内存空间
#include <stdio.h>
int main(){
//利用指针变量p指向非法内存空间 0x1100
//int* p = 0x1100;
//printf("%d\n", *p);
int* p; //也属于野指针
*p = 100;
printf("%d\n", *p); //error 非法访问内存
}
总结:空指针和野指针都不是我们申请的空间,因此不要访问。
7.4const修饰指针
const 修饰指针有三种情况1. const 修饰指针 --- 常量指针2. const 修饰常量 --- 指针常量3. const 即修饰指针,又修饰常量
#include <stdio.h>
// 1、const 修饰的 * 称为常量指针
void test01()
{
int a = 10;
const int* p = &a; //*p只读 p可读可写 等价于 int const *p = &a;
//*p = 100; //error 指针指向的值 不可以修改
int b = 20;
p = &b; //success 指针的指向可以修改
}
//2、const 修饰的 p 称为指针常量
void test02()
{
int a = 10;
int* const p = &a;//*p可读可写 p只读
*p = 20; //success 指针指向的值 可以修改的
int b = 20;
//p = &b; // error 指针的指向不可以修改
}
//3、const 修饰 * 和 p
void test03()
{
int a = 10;
const int* const p = &a; //等价于 int const * const p = &a;
//*p = 100; error 指针指向的值不可以改
int b = 20;
//p = &b; error指针的指向不可以改
}
int main(){}
技巧:看const右侧紧跟着的是指针还是常量, 是指针就是常量指针,是常量就是指针常量
7.5指针和数组
作用:
利用指针访问数组中元素
#include <stdio.h>
int main(){
int a[5]={1,2,3,4,5};
int *p=a;
for (int i = 0; i < 5; i++)
{
//printf("%d ", *(p + i));
printf("%d ", p[i]);
}
printf("\n");
// p 和 a 的区别:
printf("%d",sizeof(p));//4
printf("%d",sizeof(a));//20
}
7.6指针和函数
利用指针作函数参数,可以修改实参的值
#include <stdio.h>
void num(int *a,int *b){
int temp;
temp=*a;
*a=*b;
*b=temp;
}
int main(){
int a,b;
a=10;
b=20;
//地址传递的形参 可以修改实参
num(&a,&b);
printf("a:%d,b:%d",a,b);
}
8.结构体
结构体属于用户自己定义的数据类型,允许用户存储不同的数据类型
8.1结构体的定义和使用
语法:struct 结构体名 {结构体成员列表}
通过结构体创建变量的方式有三种:
- struct 结构体名 变量名
- struct 结构体名 变量名 = { 成员1值 , 成员2值...}
- 定义结构体时顺便创建变量
#include <stdio.h>
#include <string.h>
//struct 结构体名 变量名 = { 成员1值 , 成员2值...}
struct student{
int id;
char name[24];
float score;
};
//struct 结构体名 变量名
void test1(){
//通过结构体类型,创建结构体变量
//给结构体变量赋值的时候要按照顺序赋值
struct student s1 = { 1, "Tom", 99.9 };
//通过 '.' 符号 可以找到具体的成员
printf("id = %d\n", s1.id);
printf("name = %s\n", s1.name);
printf("score = %f\n", s1.score);
}
在定义结构体时候,顺便创建结构体变量
struct student1{
int id;
char name[24];
float score;
}s; //s代表 通过struct sutdent1创建的结构体变量
void test2(){
s.id = 2;
//s.name = "Jerry"; //error
strcpy(s.name, "Jerry");
s.score = 80;
printf("id = %d\n", s.id);
printf("name = %s\n", s.name);
printf("score = %f\n", s.score);
}
int main(){
test2();
}
8.2结构体数组
作用: 将自定义的结构体放入到数组中方便维护语法: struct 结构体名 数组名 [元素个数] ={} , ... {} } { {} ,
#include <stdio.h>
#include <string.h>
//struct 结构体名 数组名[元素个数] = { {} , {} , ... {} }
struct hero
{
int id; //id号
char name[64]; //姓名
int height; //身高
int age; //年龄
};
void test1(){
struct hero arr[5]={
{ 1, "刘备", 160, 30 },
{ 2, "张飞", 180, 31 },
{ 3, "关羽", 170, 32 },
{ 4, "赵云", 188, 34 },
{ 5, "吕布", 196, 33 }//最后一行的 ',' 可以省略
};
int num =sizeof(arr)/sizeof(hero);
for (int i=0;i<num;i++){
printf("id = %d name = %s height = %d age = %d\n", arr[i].id,
arr[i].name, arr[i].height, arr[i].age);
}
}
int main(){
test1();
}
8.3结构体指针
作用:
通过指针访问结构体中的成员
利用操作符 - > 可以通过结构体指针访问结构体属性
#include <stdio.h>
struct student
{
int id;
char name[64];
float score;
};
void test01()
{
struct student s1 = { 1, "Tom", 100 };
struct student* p = &s1;
printf("id = %d name = %s score = %.2f\n", p->id, p->name, p->score);
printf("id = %d name = %s score = %.2f\n", s1.id, s1.name, s1.score);
printf("id = %d name = %s score = %.2f\n", (&s1)->id, (&s1)->name,
(&s1)->score);
printf("id = %d name = %s score = %.2f\n", (*p).id, (*p).name,
(*p).score);
}
main(){
test01();
}
8.4结构体嵌套结构体
#include <stdio.h>
#include <string.h>
struct student
{
int id;
char name[64];
float score;
};
struct teacher{
int id;
int age;
char name[64];
struct student stu;
};
void test01()
{
struct teacher t1;
t1.id=1;
strcpy(t1.name,"a");
t1.age=18;
t1.stu.id=1;
strcpy(t1.stu.name,"b");
t1.stu.score=15;
printf("%d,%s,%.2f,",t1.stu.id,t1.stu.name,t1.stu.score);
8.5结构体做参数
#include <stdio.h>
struct student {
int id;
char name[64];
};
//地址传递
void test02(struct student *p){
p->id=18;
printf("%d\n",p->id);
}
//值传递
void test01(struct student stu){
stu.id=22;
printf("%d\n",stu.id);
}
main(){
struct student stu={1,"zsj"};
//值传递
// test01(stu);
//地址传递
test02(&stu);
printf("%d\n",stu.id);
}
总结:如果不想修改主函数中的数据,用值传递,反之用地址传递
8.6结构体中 const使用场景
用
const
来防止误操作
#include <stdio.h>
//学生结构体定义
struct student
{
//成员列表
char name[64]; //姓名
int age; //年龄
int score; //分数
};
//const使用场景
void printStudent(const struct student* stu) //加const防止函数体中的误操作
{
//stu->age = 100; //操作失败,因为加了const修饰
printf("姓名:%s 年龄:%d 分数: %d\n", stu->name, stu->age, stu->score);
}
int main() {
struct student stu = { "张三",18,100 };
printStudent(&stu);
}
9.字符串处理
1.strcpy和strncpy
.....