c语言基础

能力有限,其他内容正在路上。。。

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 语言规定在创建一个变量或者常量时,必须要指定出相应的数据类型,否则无法给变量分配内存
作用 :整型变量表示的是 整数类型 的数据

# 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 编码放入到存储单元
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. 单精度 float
2. 双精度 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.运算符

作用: 用于执行代码的运算

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赋值运算符

作用: 用于将表达式的值赋给变量

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逻辑运算符

作用: 用于根据表达式的值返回真值或假值
//逻辑非 !
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

.....

  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值