C语言学习

0x00 c语言基础

语言分类:(*)
1、机器语言:计算机能直接识别的语言—二进制语言(0101)
2、汇编语言:
3、高级语言(自然语言):C、C++、C#等语言
翻译:将高级语言转换为机器可以识别的语言(二进制 )

C语言是面向过程:
主函数: 即main函数,是程序的入口函数

注释:不参于编译
//单行注释
/*
多行注释
*/

关键字:由系统定义,不能重作其它定义
ANSI C一共只有32个关键字

auto double int struct break else long switch case enum register typedef char extern return union const float short unsigned continue
for signed void default goto sizeof volatile do if while sta
tic

C语言的特点:
1、大小写敏感。
2、无程序行概念(一行可以有多个代码)
3、可使用空行和空格
4、常用锯齿形书写格式(即缩进)

C语言结构特点:(*)
1、函数与主函数
1.1程序由一个或多个函数组成
1.2必须有且只能有一个主函数main(),可以放在程序中任一位置
1.3程序执行从main开始,在main中结束,其它函数通过嵌套调用得以执行。
2、程序语句
2.1C程序由语句组成
2.2 用“;”作为语句终止符
3、注释:不参于编译

//单行注释
/*
多行注释
*/

0x01 C语言变量类型

1、程序=算法+数据

2、C语言中类型:基本类型、构造类型、指针类型,重定义类型()。
2.1基本类型:数字型(整型、浮点型)、字符型
2.2 整型: 空间大小以64为操作系统为例
长度:长整型long、整型int 、短整型short
有无符号分类: 有符号整型 无符号整型
短整型空间:2Byte 整型空间: 4Byte 长整型:4Byte
2.3 浮点型:单 4Byte、双精度 8Byte
2.4 字符型:1Byte
2.5其它类型:结构体,数组等

3、常量和变量:
整型变量:
1、定义整型变量:分配空间 定义 类型+变量名(程序会立刻分配该类型空间大小) 规则: 1命名规则
2在同一空间不能重复定义
3先定义再引用
2、初始化
3、引用 看到变量名就先想到引用,引用就是取出该空间的内容

int b=1; //定义,初始化
printf("%d\n",b) 引用

4、字符:
1、字符常量:
‘a’ ‘A’ ‘1’
转义字符:
‘\n’ ‘’’ ‘\t’ ‘a’ ‘\0’ ‘0’
ASCII码:
‘a’ — 97
‘A’ — 65
‘0’ — 48
‘\0’ — 0
‘\n’ — 10
2、字符变量:
定义: 类型 变量名
char 变量名;
初始化:
char 变量名 = ‘a’;

char 变量名 = 97;
引用

5、命名规则 :以字母或下划线开头,以数字、字母或下划线组成。
不能以关键来命名。
6、运算符:
1、求空间大小:sizeof
2、求类型或变量的空间大小
7、强制类型转换
把int 转为float

int a=1;
float b=(float)a;
printf("%f",b); //输出a,注意这里把%d换成%f,是不行的,a的本身类型还是没变
printf("%f",(float)a);
printf("%f",10.0/20);

基础
1、存储单位:
基本单位:Byte (节字)不是bit,一个bit不能构造成一个整体有涵义的
最小单位:bit(比特)

1Byte = 8bit
             Kb    1Kb = 1024Byte
Mb    1Mb = 1024Kb	
Gb     1Gb = 1024Mb
Tb      1Tb = 1024Gb

2、计算机语言:二进制语言

3、进制:
1、二进制: 01组成
2、八进制: 07组成
3、十六进制: 0F组成
4、十进制:09组成

0x02 进制转换

输出:
1、格式化输出
printf(“控制字符串”);
1.1输出十进制整型结果:%d
printf("%d",表达式);
1.2输出浮点型结果:%f
1.3输出字符型结果:%c
1.4输出十六进制整型结果:%x
2、计算机语言:二进制语言

3、进制:
二进制:
概念:任意一个二进制数值都可用0、1共2个数字符号来表示。数码处于不同的位置(数位)代表不同的数值
1011 = 12^3 + 02^2 + 12^1 + 12^0
十进制:
概念:任意一个十进制数值都可用0、1、2、3、4、5、6、7、8、9共10个数字符号来表示。数码处于不同的位置(数位)代表不同的数值
321 = 310^2 + 210^1 + 1*10^0

八进制:概念:任意一个十进制数值都可用0、1、2、3、4、5、6、7共8个数字符号来表示。数码处于不同的位置(数位)代表不同的数值
0321 = 38^2 + 28^1 + 1*8^0 = 209

十六进制:概念:任意一个十进制数值都可用0、1、2、3、4、5、6、7、8、9、A、B、C、D、E、F共16个数字符号来表示。数码处于不同的位置(数位)代表不同的数值
0x321 = 316^2 + 216^1 + 1*16^0

4、整型常量:1、十进制 2、八进制 3、十六进制:

5、进制转换:
二进制-》十进制:
1011 = 1×2^3 + 0×2^2 + 1×2^1 +1×2^0
十进制-》二进制:除2倒取余法(结果为0结束,二进制结果为余数倒置列表)
二进制-》十六进制 (每4位二进制为一个十六进制位)
1011 1001 1101-》 0xB9D
十六进制-》二进制 (每一个十六进制位对应4位二进制)
0xB9D-》1011 1001 1101
二进制-》八进制 (每3位二进制为一个八进制位)
101-》 05
10 111-》 027
十六进制-》二进制 (每一个八进制位对应3位二进制)
027-》 10 111

0x03 有无符号数

下面输出4 4,short 2byte 表示的最大值65535 16个二进制1为65535,2的16次方为65536  65540二进制 1 14个0 100 , short只表示16位,二进制最高位1就会去掉
short a=65540;
short b=4;
printf("%d",a);
printf("%d",b);

整型常量:十六进制 八进制 十进制
十六进制 0x1ff 或0X1FF 0X1ff(大小写或混合都可)

整型变量:
定义整型变量 [singed(有符号 +/-)/unsigned(无符号)] 类型 变量名
先定义,后引用
如果不加有符号关键字,相当于有符号
即 short a 《 = 》signed a

有符号位数的最高位是符号位,即表示正负,1位负数,0为正数;其他位数为数据位
无符号数所有位都是数据位
有符号short表示范围 -32768-32777
无符号的short表示范围 0-65535

负数以补码形式存放到计算机中,正数有原码存放,负数(对有符号位来说)转换为原码去除
原码 二进制数
反码 二进制数 0变1,1变0
补码 反码+1
原码 反码 补码
+10 00001010 01110101 01110110
-10 10001010 11110101 11110110
-1 1111 1111 1111 1111

a  -1 的补码位16个1 而变量a是无符号位的变量,所以16个位都是数据位,即16个
二进制1,也就是65535
b -1 的补码位16个1 而变量b是有符号位的变量,所以15个位为数据位,即15个
二进制1,也就是-32767,但是取出负数时,会转换为原码,所以最后为-1
输出65535  -1
unsgined short a=-1;
short b=-1;
printf("%d",a);
printf("%d",b);
输出-2,1
a  原码 1111 1111 1111 1110 变量a为有符号位 最高位为符号位,为1,是负数,然后负数取出转换为原码  先-1变为反码1111 11111 11111 1101,反码在反转变为原码 1000 0000 0000 0010,为-2
b  2的16次方为65536  无符号位 全部16位数据位 最大为65535 
65537 二进制 1 0000 0000 0000 0001  而short为2byte 16位,只能取后面的16位,最后  0000 0000 0000 0001,为1
short a=65534;
unsigned short b=65537;
printf("%d",a);
printf("%d",b);

0x04 运算符与表达式


运算符和表达式:
运算符:算术,逻辑,关系,位操作,赋值,条件.....

1.算术运算符和表达式  同级自左往右

    + -  *   /  %    eg: 3+1  2-1 3*3  3/3  3%4
       3+3*6+5/1


运算符结果:每一个运算符表达式都有运算结果 (结果值是有类型)
   结果值类型:
	 1、同类型相运算:结果类型为同类型
	 2、不同类型相运算:结果类型为?
		隐式类型转换: 不同类型运算时会发生
		整型 运算 浮点型  -》double
		                字符型-》基本整型
		                单精度-》double


注意:用到取余一定要是整形。 当涉及到多目运算符,()优先级大于*/大于+-
%去除,当除数小于被除数时,结果时除数,之后就是取余
2%3=2,1%3=1 4%3=1
2.关系运算符和表达式  >    >=   <   <=    !=    == (从右往左)
   eg: a>b  a>=b  a!=b

3.逻辑运算符和表达式(从左往右)
  与&&  1 1 得1
  或||       有1  得 1
  非!     反过来
  eg:  1&&1

4.赋值运算符和表达式 
  int i; i=10;
  复合赋值运算符 += -= *= /= 

5.自增和自减 ++ --和表达式
 前自增 后自增 前自减 后自减
i++先取内容再相加1    ++i先自加1再取值 ; 

```c
#incldue <stdio.h>
int main(){
//a++ 先取值后+1   ++a 先加1后取值 
int a=0;
printf("%d\n",a);
a++;     //不是引用,单纯自增 
printf("%d\n",a);
++a;
printf("%d\n",a);
//0 1 2


int b=0;
printf("%d\n",b);
printf("%d\n",b++);//引用取值 
printf("%d\n",++b);
//0 0 2
return 0;
}

6 逗号运算符和表达式
int a=10,b=20;

0x05 判断结构与循环结构与选择结构

switch选择

char a='+';
swtich(){
case '+':add();break;    //无break时从条件开始时往下都会执行
case '-':jian();break;
defaluti:chu();
}

if判断

 语法: if(条件表达式) //为真执行自己的语句块
             {
	  语句块;
              }
             else if(条件表达式)
             {
	语句块;	
              }
             else if(条件表达式)
             {
	语句块;	
              }
.........
          else
          {

          }   

嵌套if判断

if(条件表达式) //为真执行自己的语句块
             if(表达式)//父
             {
	  if(表达式)//子
	  {
	     语句块;
	  }
	  else
	  {
	      语句块;
	  }
              }
              else
              {
	    语句块;
               }

打印下方三角形,空心矩形

#打印下方三角形
     *
    ***
   *****
   *******

#include <stdio.h>
int main(){
	int i=0;
	int j=1;
	for(i=1;i<=6;i++){
		for(j=0;j<=6-i;j++){
			printf(" ");	
		}
		for(j=1;j<=2*i-1;j++){
			printf("*");	
		}
		
		printf("\n");
	}

return 0;

}


#打印空心矩形
#include <stdio.h>
int main(){
	int i=0;
	int j=0;
	for(i=1;i<=4;i++){
		if(i==1|i==4){
			for(j=1;j<=5;j++){
				printf("*");
			}
			printf("\n");
		}		
		else if(i==2|i==3){
		
			for(j=1;j<=5;j++){
				if(j==1||j==5){
					printf("*");
				} else{
				printf(" ");
				}	
			}
			printf("\n");
		}
	}
return 0;


}

在这里插入图片描述
在这里插入图片描述

0语句块(花括号属于语句块)
{
	语句1;
	语句2;
	语句3;
	...	
}     
1、当表达式2结果为真(非0),执行语句 
	for(表达式1;表达式2;表达式3)
		语句或语句块


2、当表达式2结果为真(非0),执行语句 	
	while(表达式2)
		语句或语句块

3、先执行do语句块,再判断表达式2,若表达式2为真,继续循环,若表达式2为假结束循环。
	do
	{
	}
	while(表达式2);


4、控制语句:break;   continue;
	区别:break是结束当层循环;continue结束本次循环开始下次循环
;为空语句
表达式2不写为空,是为真,for循环为死循环 
for(; 表达式2;;)
while(i>=5); while会结合语句或语句块,结合的是空语句,是死循环 

#会打印543210-1   for循环只会结合一条语句或语句块
int i=0;
	for(i=5;i>=0;i--)
		printf("%d",i);
		printf("%d",i);

break和continue语句的判断

#是死循环,continue跳出当次循环,不会执行输出和i++,所以i值不会变化,一直为0
int i=0;
do{	
	continue;
	printf("%d",i);
	i++;
}while(i<=5);
printf("%d",i);

#输出6
int i=0;
do{
	i++;
	continue;
	printf("%d",i);
}while(i<=5);
printf("%d",i);

#输出0
do{
	
	break;
	printf("%d",i);
	i++;
}while(i<=5);
printf("%d",i);

	
	把一个数从个位十位依次输出
	int num=1548;
	while(num!=0){
		printf("%d\n",num%10);
		num/=10;
	}
	
	
	1-100中有几个9
	int i,num,total=0;
	for(i=1;i<=100;i++){
		num=i;         //如果不把i赋值给num,直接用i进行循环,会是一个死循环,i在while循环结束时值一直为0,0+1一直小于100
		while(num!=0){
			if(num%10==9){
				total++;
			}
			num/=10;
		}
	}
	printf("%d",total);
	
	判断一个数是否为对称数
	int i,num,a=0;
	i=5445;
	num=i;
	while(i!=0){
		a=a*10+i%10;
		i/=10;
	}
	if(num==a){
		printf("yes");
	}else{
		printf("no");
	}
	
	判断是否为润年
		int year;
	scanf("%d",&year);
	if(year%4==0&&year%100!=0||year%400==0){
		printf("yes");
	}else{
		printf("no");
	}

100-999中的水仙花数

	int i,ge,shi,bai;
	for(i=100;i<1000;i++){
		ge=i%10;
		shi=i/10%10;
		bai=i/100%10;
		if(ge*ge*ge+shi*shi*shi+bai*bai*bai==i){
			printf("%d\n",i);
		}
	}
判断一个数是否为水仙花数
include <math.h>
	int num;
	int n=0;
	int sum=0;
	scanf("%d",&num);
	int fr=num;
	while(num!=0){
		num/=10;
		n++;
	}
	while(num!=0){
		sum+=pow(num%10,n);
		num/=10;
	}
	if(fr==sum){
		printf("yes");
	}else{
		printf("no");
	}
/*
使用for循环求出100-1000的水仙花
水仙花数:是一个三位数 三位数分别拆开
  	个位 十位 百位 (例:151)
	个*个*个+十*十*十*百*百*百=151
*/
/*
分析步骤:
1.for基本格式 
2.怎么样求出个位 十位 百位三个上的各个数
3.进行判断 
*/
#include "stdio.h"
int main()
{
	int i;//承接初始值和最终值的一个条件
	int ge,si,ba;  
	for(i=100;i<=1000;i++)
	{
		//	再次定义变量 定义三个变量	
		ge=i%10;//除模取余 100/10余什么 
		si=i/10%10; //100/10 %10
		ba=i/100;
		if(ge*ge*ge+si*si*si+ba*ba*ba==i) 
		{
			printf("%d\n",i);
		}
	} 
		return 0;	
}



0x06 一维数组与二维数组

1.什么是数组 ,相同类型的数据放在一起就是数组

2.数组的格式 :
数据类型 数组名[常量表达式]={};

数据类型 数组名[常量表达式]={};
int arr [3]={1,2,3} ;
数组的值在使用的需要用到下标
下标从0开始
printf("%d,%d,%d",arr[0],arr[1],arr[2]);
由上内容可以得知,如果需要处理大量相同类型的数据就使用数组

数组的首地址是什么,就是数组里面第一个值

	int a[3]={1,2,3}
	int j=0;
	for(j;j<3;j++){
		printf("%d",a[j]); //输出1,2,3
		}
	for(j;j<3;j++)
	{
		printf("%d",a[j]);   //输出0,0,0
		}
	注意下方的j的值,在第一个for循环中已经改了,所以第二个for循环的j的初始值为3 

冒泡排序
第一趟,需要5次比较
第二趟,需要4次比较
……
第5趟,需要一次,排好了     

	int a[6]={1,5,8,7,4,6};
	int i,j,temp;
	for(i=0;i<5;i++){         		
		for(j=0;j<6-i-1;j++){     //-1去除自己,-i时去除已经排好的,每一趟都会少一个数
			if(a[j]>a[j+1]){
				temp=a[j];
				a[j]=a[j+1];
				a[j+1]=temp;		
			}
		}
	}
	for(i=0;i<6;i++){
		printf("%d\n",a[i]);
	}
	//注意和上面的区别,都一样
	int a[6]={1,5,8,7,4,6};
	int i,j,temp;
	for(i=0;i<5;i++){
		for(j=0;j<5-i;j++){
			if(a[j]>a[j+1]){
				temp=a[j];
				a[j]=a[j+1];
				a[j+1]=temp;		
			}
		}
	}
	for(i=0;i<6;i++){
		printf("%d\n",a[i]);
	}
	




	int i;
	int temp;
	int a[]={1,2,5,4} ;   
	for(i=0;i<=3;i++){        
		if(a[i]>a[i+1]){
			temp=a[i];
			a[i+1]=a[i];
			a[i]=temp;
//			temp=a[i];
//			a[i]=a[i+1];
//			a[i+1]=temp;  注意这俩的区别 
	
	
选择排序			 	
		1.找出数组里面最小的值的下标 并将这个值为下标为0的元素值交换一下
		2.找出第二小的值的下标, 并将这个值为下标为1的元素值交换一下
		3.依此类推 
*/
	int arr[]={5,9,7,6,1,2};    
	for(int i=0;i<5;i++)
	{
		//1.我假设第一个元素为最小值 
		int min=i;
		//最小值也就是下标0被使用了  初始值就需要从下标1开始  
		for(int j=i+1;j<=5;j++)
		{
			if(arr[j]<arr[min]) //下标j循环比下标0 的值   a[5]= 2  a[0]=5
			{
			//如果发现某一个数 比这个数小 那么交换他们的下标  
				min=j;	//min的值就是最小值的下标  
			}	
		} 
		//for循环只结束了内循环,外层循环定义的变量i还存在 
		//也就是内层循环某一次执行找不到最小值 ,也就是min不能等于他本身  
		if(min!=i)  
		{
			//交换数据顺序 
			int temp=arr[i];
			arr[i]=arr[min];
			arr[min]=temp;	
		}
	}
	
	for(int i=0;i<6;i++)
	{
		printf("%d\n",arr[i]);
	}

二维数组

数据类型 数组名 [行][列]={} || {{},{},{}}

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

定义二维数组的时候 行数可以不写,但是列数必须写

一维数组访问 数据的方式 数组名加[下标 ] 0-N
二维数组访问 数据的方式 数组名加[行 0-N][列 0-N]

for(int i=0;i<3;i++) //0 1 2 //行 
{
for(int j=0;j<2;j++)//0 1 //列 
{
printf("%d\t",arr[i][j]);
}
printf("\n");
	 
} 
//	现在一串数据 1,9,2,8,3,7,4,6定义一个二维数组 列数 2 求出
//他们的行和 以及列和 
	int arr[4][2]={1,9,2,8,3,7,4,6};
 	int rownum[4]={0}; //存行值 
 	int colnum[2]={0};//存列值
	 //行数
	 for(int i=0;i<4;i++) 
	 {
	 	//列 
	 	for(int j=0;j<2;j++)
		 {
		 	// 外层是不是0 i=0
			 //rownum[0] +=arr[0][0] 
			 //rownum[0]=rownum[0]+1=1
			 //rownum[0]=0+1=1
			 
			 //rownum[0] +=arr[0][1] 
			 //rownum[0]=rownum[0]+9=10
			 //rownum[0]=1+9=10
		 	rownum[i]+=arr[i][j];
		}	
	}
	printf("行和是。。。。。。。。。。。\n");
	for(int i=0;i<4;i++)
	{
		printf("%d\n",rownum[i]);
	} 
	for(int i=0;i<2;i++) 
	 {
	 	//列 
	 	for(int j=0;j<4;j++)
		 {
		 	colnum[i]+=arr[j][i];
		}	
	}
	printf("列和是。。。。。。。。。。。\n");
	for(int i=0;i<2;i++)
	{
		printf("%d\n",colnum[i]);
	} 
	return 0;	


兔子繁殖问题/斐波纳契数列
在这里插入图片描述


	int arr[6][6]={0};
	//给第一列的数据以及每一列的最后一个数据赋值为1 
	for(int i=0;i<6;i++)
	{
		arr[i][0]=1;
		arr[i][i]=1;
	 } 
	 // 这里面的行号为什么要从2开始 
	 //2是因为前面 的数据已经被赋值为1覆盖了
	 //列号为什么是1,因为求的这个值的顺序要从这里开始计算 
	 for(int i=2;i<6;i++)
	 {
	 	for(int j=1;j<i;j++)
		 {
		 	//套公式 ,找出这个数据的规律,直接套 
	 		arr[i][j]=arr[i-1][j-1]+arr[i-1][j];	
		 }
	 }
	 //遍历输出  
	for(int i=0;i<6;i++)
	{
		for(int j=0;j<=i;j++)
		{
			printf("%d\t",arr[i][j]);
		}
		printf("\n");
	 } 
	
	return 0;
}
int main()
{
	//现有一对兔子,2个月之后会生一对兔子,兔子从 
	//第三个月开始,每个月就会生一对兔子,问
	//一年之后有多少兔子
	
	//指明二维数组写
	//1.定义出二维数组的大小[12][2] 
	//2.第一个只有一个小兔子
	//3.把这个小兔子放到数组里面
	//[0][0]=0   [0][1]=1 
//	规律:下一个月兔子的总数 是前两个月之和
	
	
	int arr[12][2]={0};
	arr[0][0]=0;
	arr[0][1]=1;
	for(int i=1;i<12;i++)
	{
		//下一个月的成年兔子,是上一个月之和 
		arr[i][0]=arr[i-1][0]+arr[i-1][1];
		//上一个月的成年兔子,是下一个月小兔子
		arr[i][1]=arr[i-1][0];
		
		int sum=arr[i][0]+arr[i][1];
		printf("%d\n",sum);		
	}
printf("%d\n",MAX);	

杨辉三角
1
1 1
1 2 1
1 3 3 1

	int arr[6][6]={0};
	//给第一列的数据以及每一列的最后一个数据赋值为1 
	for(int i=0;i<6;i++)
	{
		arr[i][0]=1;
		arr[i][i]=1;
	 } 
	 // 这里面的行号为什么要从2开始 
	 //2是因为前面 的数据已经被赋值为1覆盖了
	 //列号为什么是1,因为求的这个值的顺序要从这里开始计算 
	 for(int i=2;i<6;i++)
	 {
	 	for(int j=1;j<i;j++)
		 {
		 	//套公式 ,找出这个数据的规律,直接套 
	 		arr[i][j]=arr[i-1][j-1]+arr[i-1][j];	
		 }
	 }
	 //遍历输出  
	for(int i=0;i<6;i++)
	{
		for(int j=0;j<=i;j++)
		{
			printf("%d\t",arr[i][j]);
		}
		printf("\n");
	 } 
	
	return 0;
}

0x07 函数与字符串

函数就把一个具有某种功能的代码单独提取出来 ,放在一个作用域内,这个作用域可以多次访问 叫函数
函数的格式

返回值类型 函数名(数据类型 形参1,类型类型 形参2){
//函数体
return ;
}

有返回值
//求两个数相加的和 
int aa(int x,int y) //无形参可不写 
{
	int sum=x+y;
	return sum,x;  //这里只会返回x的值	
}
无返回值
void aa(int x,int y) //无形参可不写
{
int a=1;
int b=2;
if(a<b){
int temp=a;
a=b;
b=temp;
}
return ;
}
int main()
{
	//调用函数,因为是有返回值的函数,你想要拿到这个返回的数据 
	//就必须要有一个相同类型的变量来承接他 
	int al=aa(3,4); 
	printf("%d",al);
	return 0;
}

1.char类型可以是字符类型,但是不一定是字符串类型 字符串以’\0’
2.字符串的数据,可以以字符的格式输出

字符数组定义

char a[5]={'A','B','C','D','E'};

字符串

char arr1[]={'a','b','c','\0'};
char arr1[11]={"qwertyuiop"};
printf("%s\n",arr1);

获取数据 scanf 与 gets 的区别
scanf 输入的数据不能有空格,会吞字符
gets 输入的数据允许有空格

char arr1[5];
scanf("%s\n",arr1);
printf("输入的数据是%s\n",arr1);
getchar();         //只能获取一个字符输入 putchar(arr1) 只能获取一个字符输出 
printf("--------------\n"); 
printf("gets ");
gets(arr1);  //输入字符串
puts(arr1); //输出字符串
//现有一串英语句子 "how are you"统计出其中有几个单词 
//中间一以空格隔开
//1.先定义一个char类型的数组(未告诉他是字符还是字符串) 
//2. gets输入数据
//3.遍历判断	
char a1[100]; 
int count=0;
printf("请输入 :");
gets(a1); 
for(int i=0;i<strlen(a1);i++)
{
if(a1[i]==' '){
count++;
printf("%c",a1[i]);	
}
}
count++;
printf("一共有%d\n",count); 

来字符数组和字符串的长度
1.strlen :
不会获取 \0 ,只会获取数据本身

int i=strlen(arr1);
printf("%d\n",i); 

2.复制粘贴 strcpy

char arr1[100]={"awerrtty"}; //A 65 a 97
char arr2[100]={"bbcdefgh"};
strcpy(arr2,arr1);//把arr1里面的数据赋值给arr2 
printf("%s\n",arr2);	 

3.比较字符长度大小
如果第一个字符串小于第二个 会返回一个小于0的数
如果第一个字符串大于第二个 会返回一个大于0的数
如果说他们俩个相等 就返回0

int i=strcmp(arr1,arr2); 
printf("%d\n",i); 

4.把两个数组拼接起来(strcat)

printf("%s\n",strcat(arr1,arr2));

从键盘输入一串字符串,输入字符串的数据不超过19
每行输出不超过4个字符,不足4个字符补*,如果没有数据不做判断,要使用strlen函数 ,NULL

  
 char arr[20];
printf("请输入:");
gets(arr);
int count=0;
//获取*号缺多少个
int len=strlen(arr);//获取数组的长度 
int aaa=4-(len%4);   //获取要补几个** 
if(len==NULL){
printf("没数据");
return 0; //这里写return 代表后面的代码都 不执行 
} 
for(int i=0;i<len+aaa;i++) //这里+aaa 是为了把*号输出出来,len只能获取现有数据 
 {
	if(i<len){	//输出键盘输入的数据 
	printf("%c",arr[i]);
	}else{
	printf("*"); 
	}
	count++; //为换行做准备 
	if(count%4==0){//满足四个换行 
	printf("\n");
	}
 } 

函数递归
1.递归调用 ,就是函数自己调用自己
2. 截止条件,规律

月份1  2  3  4  5  6  7   8   9
总数1、1、2、3、5、8、13、21、34
//兔子繁殖问题/斐波纳契数列
int f(int i)
{
	if(i==1||i==2){
		return 1;
	}
	return f(i-1)+f(i-2);
	//F(6-1)+F(6-2)
	//F(5)+F(4)		
}

int main()
{ 	
	printf("%d\n",f(6));	
	return 0;
}


有有5个人坐在一起,问第五个人多少岁?
他说比第4个人大2岁。
问第4个人岁数,
他说比第3个人大2岁。
问第三个人,
又说比第2人大两岁。
问第2个人,说比第一个人大两岁。
最后问第一个人,他说是10岁。

#include "stdio.h"
int f(int i)
{
	if(i==1){
	 return 10;
	}
	return f(i-1)+2;	
	//f(5-1)+2  f(4-1)+2   f(3-1)+2  f(2-1)+2
	//+2  +2   +2  10+2  
}

int main()
{
	printf("%d",f(5));
	return 0; 
} 

汉诺塔

#include "stdio.h"
	/*
		汉诺塔 
		假设有ABC 三根柱子 
		1.把A柱子上面的所有圆盘全部移动到C柱上面
		2.一次只能移动一块
		3.大盘不能放在小盘上面  
		
		假设我现在这里只有一块盘子
		 A->c
		假设我现在这里只有二块盘子
		 A->B  A->C  B->C 
		设我现在这里只有三块盘子
		A->C  A->B C->B  A->C B->A
		B->C  A->C
	条件:每当我A柱上面有盘子的时候都会移动到C柱上面
		
		假设有N  N-1  N-2 N-3
		
	规律 :把N层以上的全部看成一个整体,那么现在,
		我现在就可以只求两行怎么交换了 
	*/
int m=0;
void f(int i,char a,char b, char c)
{
	m++;
	if(i==1){
		printf("%c->%c\n",a,c);
	}else{
		f(i-1,a,c,b);//拿C柱做中间柱,把所有的数据传到b柱上面 
		printf("%c->%c\n",a,c);
		f(i-1,b,a,c);		
	}	
}
int main()
{
	int num=4;
	f(num,'a','b','c') ;
	printf("共移动了%d\n",m);
	return 0;
} 

0x08 指针

指针就是地址,一个指针不能赋值给另一个不同类型的指针

int a=10;
int *p=&a;//指针变量的定义及赋值
//指针变量指向了a的地址
//如何查看地址
printf("%p\n",&a);
printf("%p\n",p);
//如何查看他的值
printf("%d\n",a);
printf("%d\n",*p);

指针里面只要查看指针变量的大小 都是8位(64位) 4位(32位)
指针如何操作数组 ,自增,自减,两个指针之间相减,指针之间的关系运算

< != ==

/*
	int a=10;
	int *p=&a;
	char cc='A';
	char *pc=&cc;
	double dd=1.14;
	double *pd=&dd;
	//指针里面只要查看指针变量的大小 
	//都8位(64) 4(32) 
	printf("%d\n",sizeof(p));
	printf("%d\n",sizeof(pc));
	printf("%d\n",sizeof(pd));
*/
int main()
{
//对指针本身进行自增和自减 
int a=10;
int *p=&a;
printf("原始数据\n");
printf("%p\n",&a);	
printf("%p\n",p);
p++;printf("自增后\n");  //p=p+1 
printf("%p\n",&a);	
printf("%p\n",p);
p--;printf("自减后\n");
printf("%p\n",&a);	
printf("%p\n",p);

//两个指针之间如何来进行+ -操作
//多个指针之间没有加法的操作
//减法主要用于干什么(求两个指针之间的字节数)

	int *p=(int *)10000; 
	int *p1=(int *)10012;
printf("%d\n",p1-p); 
//printf("%d\n",p1+p); 

//指针之间的关系运算
//	> < != ==
	
//比的是地址的大小  
	printf("%d\n",p<p1);
	if(p<p1){
		printf("ppppppp");
	}else{
		printf("1111111");
	}
//!= == 
	printf("%d\n",p==p1);
	if(p==p1){
		printf("ppppppp");
	}else{
		printf("1111111");
	}	 
	
}

指针如何操作数组


//数组是线性的方式来存储 
int main()
{
 int arr[]={1,2,3,4,5};
 int *p=arr;//把指针的首地址赋值给这个p,arr表示数组的首地址,arr[0]表示的是值
 int *p1=&arr[0];
 printf("%d %d %d\n",arr[0],*p,*p1); 
 printf("%p %p %p\n",arr,p,p1); 
  
 int len=sizeof(arr)/sizeof(arr[0]);
 for(int i=0;i<len;i++)
 {
 	printf("%d\t\n",arr[i]);
 	printf("%d\t\n",*(arr+i));
  	printf("%d\t\n",p[i]);
	printf("%d\t\n",*(p+i));	
	 printf("%d\t\n",p1[i]);
	printf("%d\t\n",*(p1+i));

 }
 
 //定义一个指针指向数组(要有6个值)的第3个数,
 //并开始遍历
 int arr1[]={1,2,3,4,5,6};
 int *aa=&arr1[2];
// printf("%p\n",arr); //数组名,只充当首地址,不参与运算 
// printf("%p\n",&arr[2]);
// printf("%p\n",aa);
printf("-----------\n");
for(int i=0;i<4;i++)
{
	printf("%d\n",aa[i]);	
} 
 
//最后输出的值为2,6
 int a111[5]={1,2,3,4,5} ;
// int *ptr=(int *)(&a+1); 
 int *ptr=a111;
printf("%p\n",a111); 
printf("%d\n",*(a111+ 1)); //一个是遍历里面的值 
printf("%d\n",*(&a111+1)); //一个是对数组整体进行,需要加5*4个字节,20个字节,也就是a[5]						
}

定义一个函数(形参要用到指针变量)
来交换三个变量的值
让其从小到大排列 用到指针*p1 *p2 *p3
假设值是 10 5 7 结果 5 7 10

	int a=10,b=5,c=7;
	int *p1,*p2,*p3;
	p1=&a;p2=&b;p3=&c;
	printf("初始值%d,%d,%d\n",a,b,c);
	swap(p1,p2);swap(p2,p3);
	printf("最终值%d,%d,%d\n",a,b,c);
	printf("最终值%d,%d,%d",*p1,*p2,*p3);			
	return 0;	
void swap(int *p1,int*p2)
{
	int temp=*p1;//直接改变a,b,c 
	*p1=*p2;
	*p2=temp;
}

0x09 结构体,共用体

结构体 => 类(java、python、C#)
结构体的定义方式:
1.struct 结构体名 {数据类型1 变量1} 结构体变量 ;
2.struct 结构体名 {数据类型1 变量1} ;
struct 结构体名 结构体变量;
如何使用:
通过 变量名.里面某一个变量

结构体数组
1.struct 结构体名 {数据类型1 变量1} 结构体变量[3] ;

共同体和结构体类似
1.union 共同体名 {数据类型1 变量1} 共同体变量 ;
2.union 共同体名 {数据类型1 变量1} ;
union 共同体名 共同体变量;

特点 :
1.不能够同时对多个变量赋值
2.只能看到最后一次赋值的那个值
3.共同体没有数组

结构体和共同体的注意点:
1.共同体以最大的数据类型做整个共同体的大小
2.最后的字节大小须为最大字节类型的空间大小的倍数

//方法一 
	struct student {
	char name[20];//名字 
	int age;//年龄  
	}s1={"张三",18};
	printf("%s,%d\n",s1.name,s1.age); 
	
	struct student {
		char name[20];//名字 
		 int age;//年龄  
	};
	
	struct student s1;
//	s1.name="张三";//错的 
	strcpy(s1.name,"张三"); //把右边的值赋值给左边的这个属性 
	s1.age=18;
	printf("%s,%d",s1.name,s1.age);
共用体
	union student {
		char ch;  
		int age;
	}s1;
	
	s1.ch='f';
	printf("%c\n",s1.ch);
	s1.age=18;
	printf("%d\n",s1.age);
	//s1.ch='f';   同时赋值会报错
	//s1.age=18;

结构体数组
struct student {
		char name[20];//名字 
		 int age;//年龄  
	}s1[3]={
		{"张三",18},//0
		{"李四",19},//1
		{"王五",20},//2
	};
	int sum;
	//for 用知道循环遍历多少次 
	for(int i=0;i<3;i++)
	{
		printf("%s,%d\n",s1[i].name,s1[i].age); 
		sum=sum+s1[i].age;
	} 
	printf("%d",sum);


结构体,共用体所在空间大小
	struct student {
		 char name; //  1
		 int age; //   4
	}s1;	
	printf("结构体的大小=%d",sizeof(s1)) ; //为8
	
	union student {
		char ch;  
		int age;
	}s1;
	printf("共同体的大小=%d\n",sizeof(s1)); //4

0x10 文件

“r” 打开一个用于读取的文件。该文件必须存在。
“w” 创建一个用于写入的空文件。如果文件名称与已存在的文件相同,则会删除已有文件的内容,文件被视为一个新的空文件。
“a” 追加到一个文件。写操作向文件末尾追加数据。如果文件不存在,则创建文件。
"r+"打开一个用于更新的文件,可读取也可写入。该文件必须存在。
"w+"创建一个用于读写的空文件。
"a+"打开一个用于读取和追加的文件。

文件
1.打开文件 fopen (“文件地址及名称”,“读写模式”) 会返回一个文件的IO流
2.写入数据 fprintf(“位流”,“数据类型占位符”,数据)
确定文件的读取地址 fseek(位流,字节偏移,SEEK_SET)
SEEK_SET 文件的开头
SEEK_CUR 文件指针的当前位置
SEEK_END 文件的末尾
3.读取数据 fgets(数组变量,读取取长度,位流)
4.关闭文件 fclose(fp);

注意点:为什么写入没有数据显示,指针偏移问题

int main()
{	
	FILE *fp=fopen("C:\\Users\\Administrator\\Desktop\\NONGFU.TXT","w+"); 
	if(fp==NULL){
		printf("文件打开失败\n");
		return 0;
	}
	fprintf(fp,"%s","123456789"); //写入数据到文件 里面 
	
	fseek(fp,2,SEEK_SET); //移动文件指针的 位置到开头,并偏移2位 
	
	char arr[100];//定义一个字符串的数组 
	if(fgets(arr,100,fp)!=NULL){ //判断是否能正常读取文件信息 
		printf("%s",arr);	 //如果能够正常读取就输出 
	}
	fclose(fp); //关闭文件流 
	return 0;
}
  • 29
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值