小破站-郝斌-C语言随笔记录

2020/11/12

为了考试,回来学C语言,虽然我是先肝java 后肝c 的,但还是想说,先看c 再看java 确实更方便于理解

想想刚开始的时候,,,啥叫面向对象,一脸懵逼?-?

三连传送门:https://www.bilibili.com/video/BV1os411h77o


在这里插入图片描述
如何学习一些需要算法的程序【如何掌握一个程序】

  1. 尝试自己去编程解决它
    但要意识到大部分人都是自己无法解决的,这时不要气馁,也不要放弃
    如果十五分钟还想不出来,此时我建议您就可以看答案了
  2. 如果解决不了,就看答案
    关键是把答案看懂,这个要花很大的精力,也是我们学习的重点
    看懂一个程序要分三步:流程、每个语句的功能、试数
  3. 看懂之后尝试自己去修改程序,并且知道修改之后程序的输出结果的原因
    不建议看懂程序之后就立即自己敲程序
  4. 照着答案去敲
  5. 调试错误
  6. 不看答案,自己独立把答案敲出来
  7. 如果程序实在无法彻底理解,就把它背会,不过无法彻底理解的程序
    我自己只有在学数据结构时碰到过一个,学其他语言都没有碰到过

算法或程序学习思路—》千万别钻牛角尖

大多数人都有着想法,一道算法题看起来很简单,就感觉我一定要把它做出来,那么简单怎么能难道我呢,
结果可能做出来了,也可能是没做出来—》我以前就是这样的
.
.
其实正确方法是,这题看15,20分钟之后,确实不会,那就看答案吧,
看完答案,理解了,先别急着敲,把这源码改一下,加深理解,顺便看看会发生什么,
然后再自己敲一遍,敲完了运行,若是没有出错也就算了,但往往是会出错的~
其实出错是好事,出错了就需要去排错,这个过程能加深你对这程序本身的理解。

看懂程序的三步走
1、流程
2、每个语句的功能
3、试数(试试改一下再运行会发生什么)

概述

在这里插入图片描述

起源和发展

1、程序语言的发展

Fortran语言主要用于计算;Basic语言目前没有大量使用,转化为VB;Pascal语言主要用于教学。c语言在结构性语言中是非常重要的,是结构化的代表。
因为结构化语言有缺陷,所以出现面向对象语言,C++是面向对象中最复杂最重要的语言,Java也是从中发展出来的。
Java的运行慢,但是任何机器上都可以运行。C语言运行最快,c++其次。

B语言是首先创造第一个Unix系统,一般用于大型商务机,该系统非常稳定。
C语言必学:函数、指针。

特点

1、优点
代码量小、速度快、功能强大。
1)、wps由金山公司设计,由C语言设计,代码容量小。
2)、操作系统:Windows(内层是C语言写的和外层是c++写的)、unix(C语言写的)、Linux(C语言写的)。操作系统速度要保证快且在运行软件时也要快,Java的运行慢不可以用来写操作系统。
3)、操作系统运行软件也可以操作硬件,所以C语言编写的操作系统功能强大。
2、缺点
危险性高、开发周期长、可移植性弱
1)、C语言的查错性很差,对于小错误不报,导致很多问题
没有被屏蔽。
2)、当代码很长时看起来很难找到结构。
3)、Java移植性强,各个机器执行的结果不同,导致差错。

C语言的应用领域
在这里插入图片描述
如何学习C语言
理论+实践

逐步加难加深

C语言是面向过程;Java是面向对象。
Java中引用的本质就是C语言中的指针。

课程计划23讲

在这里插入图片描述

C语言预备知识

在这里插入图片描述

  • 1.工作流程:
    《猛龙过江》.mp4→操作系统→硬盘→内存条→CPU→显卡、声卡→显示器、音响

  • 2.运行helloworld.cpp

#include<stdio.h>
#include<math.h>
int main(){
    printf("111dasdasdadasdas\n" );
    system("pause");
    return 0;
}

3.数据类型

  • 基本数据类型
    在这里插入图片描述
    字符型
    char

  • 复合数据类型
    结构体
    枚举
    共用体

操作系统–》vc+±-》内存条–》CPU

  • 4.什么是变量
    变量的本质:内存中的一段存储空间
    int = i; //给变量 i 分配内存空间,i 指向内存地址
    i=3; //往内存中存入数据

    – > 3 存放在内存中,程序终止后3所占用的内存空间会被释放,操作系统回收该内存空间,但不会清空该内存空间遗留下来的数据

  • 5.变量为什么要初始化,初始化=赋值
    若是发现 i 没有初始化(赋值),vc++会自动填充一个很大的负数进去
    弹幕举例:
    一、可以吧内存条比喻为一排房子
    二、变量i就相当于给其中一套房子起上名字并且能被 i 使用
    三、给 i 赋值就相当于往房子里面放了一个人
    四、而在这个房子里存放的数据是以1和0来进行记录的

.6.
在这里插入图片描述
7.
在这里插入图片描述
在这里插入图片描述
8.
在这里插入图片描述
在这里插入图片描述
9.
在这里插入图片描述
字符串
在这里插入图片描述
10.
在这里插入图片描述

printf 的用法(进制转换)

int i =10; // i 的值为10,是以二进制来保存的
printf(“i=%d”,i); //这句话是把 二进制 i 的值,转换成十进制输出
在这里插入图片描述

1、100转换成二进制为1100100,步骤如下:

(1)将100按照2的加权项展开。

在这里插入图片描述
(2)从右向左填充二进制数字。
在这里插入图片描述
2、100转换成八进制为144,步骤如下:

(1)100的二进制结果“1100100”,从右向左每三个数字分为一组。
在这里插入图片描述
(2)将每组的结果分别转换为八进制。
在这里插入图片描述
3、100转换成十六进制为64,步骤如下:

(1)100的二进制结果“1100100”,从右向左每四个数字分为一组。
在这里插入图片描述
(2)将每组的结果分别转换为十六进制。
在这里插入图片描述
在这里插入图片描述
int i ;
scanf("%d",&i);// &i 表示i 的地址,&是一个取地址符
printf(“i=%d”,i);

弹幕评论:
一个地址对应一个内存空间,&i 相当于一个地址门牌号,scanf是将手输入的东西放到地址所对应的内存空间中

printf是从右向左看
scanf是从左往右看。

scanf(“m%d”,&i); //非输入控制符必须原样输入
必须输入m 开头的数字,比如m1234,m123n

.

运算符
在这里插入图片描述
区别
16/5=3
16/5.0=3.20000

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

流程控制–重点-1

在这里插入图片描述
90 <= i <= 100
90 <= i 为逻辑值,为真则1 或为假则0,
所以(90 <= i) <= 100 ----> 1(或0) <= 100 恒成立

在这里插入图片描述

两个整数之间有无数个数,计算机存储不下,只能存储中间的n个数,所以浮点数可能有误差。

循环更新的变量不能更新成浮点型,因为浮点型不能准确存储
例如:

float i = 99.9;
printf("%f",i);

输出结果为:99.900002

进制

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

在这里插入图片描述

其他的一些运算知识


为何会出现自增
1.代码更精炼
2.自增速度更快

学习自增要明白几个问题
1.编程时应该尽量屏蔽掉前自增和后自增的差别
2.i++ 和 ++i 单独成一个语句,不要把它作为一个完整复合语句的一部分来使用
或者说 自增表达式最好不要作为一个更大的表达式的一部分来使用

例子:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


数字颠倒算法 或 回文数算法

#include<stdio.h>
int main(){
	
	int num=0;
	int m=0;
	int val;
	
	printf("请输入数字:");
	scanf("%d",&val);
	
	m=val;
	while(m!=0){
		num = num * 10 + m%10;
		m /= 10;
	}
	printf("%d\n",num);
	
	if (num == val){
		printf("yes\n");
	}else{
		printf("no\n");
	}
	return 0;
}

分析:
在这里插入图片描述
在这里插入图片描述

一元二次方程

1、C语言基本框架格式:

2、代码步骤
1)、定义变量,将方程的三个系数保存在计算机中;定义bb-4a*c判断根的个数;定义存放方程的结果值的变量。
2)、判断根的情况来来求解。
注意:sqrt()用于求平方根的函数;并且此工具在math.h文件中,所以开头要写:

include <math.h> 引入该文件

代码:

#include <stdio.h>
#include <math.h>
int main(void){
	
	double a,b,c;
	double delta; 
	double x1,x2; 
	char ch;
	
	do{
		printf("请输入一二次方程的三个系数:\n");
		printf("a=");
		scanf("%lf",&a);
		
		printf("b=");
		scanf("%lf",&b);
		
		printf("c=");
		scanf("%lf",&c);
		
		delta=b*b-4*a*c;
		
		if (delta > 0){
			x1=(-b + sqrt(delta)) / (2*a);
			x2=(-b - sqrt(delta)) / (2*a);
			printf("有两个解,x1=%lf,×2=%lf\n",x1,x2);
		}else{
			printf ("无实数解! \n");
		}

		printf ("您想继续么(Y/N) : ");
		scanf (" %c", &ch) ; //%前面业须得加一个空格原因略
	} while ('y'==ch || 'Y'==ch);
	//do...while用于人机交互
	return 0;
}

switch的用法

电梯案例

#include <stdio.h>
int main(void){
	int val;
	printf ("请输入您要进入的楼层: ");
	scanf ("%d", &val);

	switch (val){
	case 1:
		printf ("1层开!\n");
		break;
	case 2:
		printf ("2层开!\n");
		break;
	case 3:
		printf ("3层开!\n");
		break;
	default:
		printf ("没有盖到这一层!\n");
		break;
	}
	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在多层for循环或在多层switch语句中,break只能终止离它最近的那个循环
在这里插入图片描述

数组

在这里插入图片描述
1、一位数组

赋值
排序
求最大/最小值
倒置
查找
插入
删除

简单的数组倒置算法原理

#include <stdio.h>
int main(void){
	
	int a[8]={1,2,3,4,5,6,7,8};
	int i,j,t;
	
	i=0;//数组初始位
	j=7;//数组末尾位
	while(i<j){//互换
		t=a[i];
		a[i]=a[j];
		a[j]=t;
		
		i++;
		j--;		
		}
	for(int aa=0;aa < 8;aa++){
		printf("数字=%d\n",a[aa]);
	}
	return 0;
}

2、二维数组
在这里插入图片描述
printf("%-5d",a[a][j]);%-5d和%d\t有异曲同工之妙
-5是从左数添加5个空格,\t是表格形式输出

对二维数组排序
求每一行的最大值
判断矩阵是否对称
矩阵的相乘

在这里插入图片描述
3、三维数组

3、4、5走成一条线,每个五个5隔着个4,每四个4隔一个3
3行4列,4列中每一列都有5个元素

{ {5},{5},{5},{5},{5} }{ {5},{5},{5},{5},{5} }{ {5},{5},{5},{5},{5} }{ {5},{5},{5},{5},{5} }
{ {5},{5},{5},{5},{5} }{ {5},{5},{5},{5},{5} }{ {5},{5},{5},{5},{5} }{ {5},{5},{5},{5},{5} }
{ {5},{5},{5},{5},{5} }{ {5},{5},{5},{5},{5} }{ {5},{5},{5},{5},{5} }{ {5},{5},{5},{5},{5} }

函数–重点-2

在这里插入图片描述

什么叫做函数

在这里插入图片描述

避免重复性操作
有利于程序的模块化

c的函数很像java的方法,都是一个工具类

在这里插入图片描述
max函数压栈,执行完后max函数出栈
当一个函数使用完之后,它的内存空间会被释放掉

如何定义函数

函数定义的本质是详细描述函数之所以能够实现某个特定功能的具体方法

return的解释
在这里插入图片描述
在这里插入图片描述

函数的分类

如果,功能相似,数据不同,而且要写很多重复性代码,这时就可以把这个功能封装成函数
传入参数直接调用该函数就行了
在这里插入图片描述
判断输入值的是否为素数

#include <stdio.h>
bool Sushu(int val){
	bool flag;
	int i;
	
	for (i=2; i<val; ++i){
		//在2~val的范围内,如果有一个能被val整除的数,则i 不可能==val
		if (val%i ==0)
			break;
	}
	if (i == val)
		return true;
	else
		return false;	
}
int main(){
	
	int val;
	// int i;
	
	printf("请输入数字:");
	scanf ("%d", &val);
	
	if(Sushu(val)){
		printf("是素数\n");
	}else{
		printf("不是素数\n");
	}

		return 0;
}

注意的问题
在这里插入图片描述
4. 对函数的声明是通过 #include <库函数所在的文件的名字.h>来实现的
<sdtio.h>是一个标准的(standard)输入输出(io)的函数库(.h)

  • 形参和实参
    个数相同 位置一 一对应 数据类型必须相互兼容

  • 如何在开发中设计函数来解决实际问题
    1、一个函数的功能尽量独立,单一
    2、多学习,多模仿大神是怎么写的

例子

目的:输出2~n之间的所以素数

第一步:设计一个函数判断,用来判断是否为素数(封装函数方法)

#include <stdio.h>
//判断是否为素数,是返回true,否返回false
bool sushu(int val){
	int i;
	
	for (i=2; i<val; ++i){
		//在2~val的范围内,如果有一个能被val整除的数,则i 不可能==val
		if (val%i ==0)
			break;
	}
	if (i == val)
		return true;
	else
		return false;	
}

第二步:遍历2~n的所有数字,并逐个判断是否为素数(封装函数方法)

//把2~n的所以素数显示出来
void sushuval(int n){
	int i;
	
	for(i=2;i <= n;i++){
		if(sushu(i)){
			printf("%d\n",i);
		}
	}
}

第三步:调用函数

int main(void){
	
	int val;
	
	printf("请输入数字:");
	scanf ("%d", &val);
	sushuval(val);//调用函数
	
		return 0;
}

常用的系统函数

函数是C语言的基本单位,类是Java, C#, C++的基本单位

在这里插入图片描述

专题:递归
在这里插入图片描述

指针–重点-3

指针和地址是一个概念
地址是内存单元的编号
指针和指针变量是两个概念,指针是收,指针变量是名字
指针的本质是一个操作受限的非负数
指针变量就是存放内存单元编号的变量
地址和指针都是只能作减法运算,不能加乘除

int * p; p 是变量的名字, int *表示p变量存放的是int类型变量的地址
int i = 3;

int *是数据类型,p 才是名称
int *类型就存放int 变量地址的类型

p是指针变量,是存放地址的变量
i 是普通变量

赋值时候,p=i; 是错的,
p只能存放i 变量的地址,不能存放i 变量的值
所以要用取地址符&,p=&i ; 这才是对的

p=&i ;
1、p 保存了i 的地址,因此p 指向 i
2、p不是i , i 也不是p,更准确的说: 修改p的值不影响i的值,修改i 的值也p的值
在这里插入图片描述
3、
在这里插入图片描述
*p 是以p的内容为地址的变量,也就是说,p=&i ;,*p的值就是i 的地址了,此时*p就是以i 的地址为p的内容的变量了

这个时候*p 就等于 i 了,而p 则为单独的一个地址变量

#include<stdio.h>
int main(){
	int * a;
	int i=2;
		a=&i;

	printf("a=%d\n*a=%d\n",a,*a);
	return 0;
	//结果为:
	//      a=2293316  被分配第一个空间
	//      *a=2	   被分配的第二个空间
	//还有一种情况,若a是未初始化的垃圾值,a能读取,但*a是不能读取的
} 

弹幕评论:
i 的普通地址不等于p 的指针地址,唯一的联系是p 存放了i 的地址
所以修改p的值(p的值是地址)不影响i 的值(i 的值是变量值),修改i 的值(变量值)也不会影响p 的值(p存放i 的地址)
.

指针的重要性

在这里插入图片描述

其中

指针的分类

1. 基本类型指针【重点】

指针常见的错误
在这里插入图片描述
弹幕评论:
p、q、r 都指向A的动态地址空间
free§不是释放这个p,而是p指向的空间
所以连同q、r指向空间一同释放了

经典的指针程序
在这里插入图片描述
在这里插入图片描述
结果为a=3,b=5
a和b是静态地址,是不会改变的

在这里插入图片描述
结果为a=5,b=3

通过指针,使形参间接修改实参
即通过指针,使被调函数修改主调函数
在这里插入图片描述

2. 指针和数组【进阶内容】

在这里插入图片描述
在C语言中,数组名代表数组中首元素的地址“(谭浩强C)

int a[5];
printf("%#X",&a[0]);
printf("%#X",a);
//结果相等,&a[0]==a

在这里插入图片描述
例子1:

int * p;
int a[5]={1,2,3,4,5};
p=a;//a等于int * 类型,这是p 指向了数组a[] 的地址
printf("%d\n",*(p+0));//*(p+0) == p[0] == a[0]  == *(a+0)
printf("%d\n",*(p+1));//*(p+1) == p[1] == a[1]  == *(a+1)

例子2:

#include<stdio.h>

void f(int * p,int len){
	
	for(int i=0;i<len;i++){
		printf("%d\n",*(p+i));
	}
}
int main(void){
	
	int a[5]={1,2,3,4,5};
	
	f(a,5);
	
	return 0;
}
  • 确定一个一维数组需要几个参数?
    [如果一个函数要处理一个一维数组,则需要接收该数组的哪些信息]
    1.数组第一个元素的地址
    2.数组的长度

没有一个有效的字符是以\0 结束的,
即\0 不代表任何一个有效字符,所以可以以\0 作为字符串结束的标志

在这里插入图片描述
一般用于数组

int a[5];
int \* p;
int \* q;
p=&a[1];
q=&a[4];
printf("pq像个%d个空间",(q-p));

弹幕:
指针的运算相当于仿射空间的运算,指针是点,整形是向量
点可以加上或减去一个向量变成另一个点
点与点的差是一个向量
但是点不能与点相加

下面指针变量的字节是–》非重点
在这里插入图片描述
答案:p q r 本身所占的字节数是一样的,为 4 或 8;
在这里插入图片描述

int main(void){
	int i=99;
	double aa=99.6;
	char ch='a';
	int * p;
	double * q;
	char * r;
	p=&i;
	q=&aa;
	r=&ch;
	
	printf ("%d %d %d\n", sizeof (p), sizeof (q), sizeof (r));
	///结果为 8 8 8 
	return 0;
}

弹幕评论:
根据数据总线数决定其指针变量所需空间
总数是32位,则指针变量为4个字节,
总数为64位,则指针变量为8个字节

但这跟电脑的位数无关,而是和你用的软件控制台应用是win32还是win64有关
与操作系统位数无关,与编译器位数有关
所以32位等于 4 4 4 个字节,64位等于 8 8 8 个字节

.
3.指针和函数【进阶内容】
4.指针和结构体
5.多级指针

3.4.5这三个下面会讲到

专题:动态内存分配–重点,难度较大

1、传统数组的缺点

在这里插入图片描述

弹幕评论:
然而动态缺点在于不管你用不用它会一直占着那个位置

2、为什么需要动态内存的分配

在这里插入图片描述

3、动态内存分配举例–动态数组的构造

malloc是memory (内存) allocate(分配)的缩写

指针变量不知道指向的变量占的是几个字节,
可以通过返回的第一个字节和变量类型(int)来确定该变量的字节
int * p = (int *)malloc(4); //分配4个字节的内存,4/4=1,动态分配1 个指针变量
char p = (char)malloc(4); //分配4个字节的内存,4/1=4,动态分配4 个指针变量
在这里插入图片描述
在这里插入图片描述
p系统本身分配的内存,是不会有错的
但*p 是动态分配的内存,执行free§之后,那动态分配的4个字节的内存已经被释放掉了,所以再调用*p 就是错的,这时调用*p 会返回一个垃圾值
在这里插入图片描述
(4 * len)相当于(sizeof(int)* len)
因为返回的pArr第一个地址是整形int的类型地址,就是按照整形地址划分内存。所以是int 类型的数组,而长度是len ,名词是pArr
在这里插入图片描述
动态改变内存需要配合函数realloc(*,*) 使用

4、静态内存和动态内存的比较

在这里插入图片描述

5、跨函数使用内存的问题

多级指针
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
结构体

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
图中的 2.指针变量名->成员们【是重点】

指针变量名->成员名 在计算机内部会被转化成(*指针变量名).成员名的方式来执行

例子:关联指针
第一种 这只是定义了一个新的数据类型,并没有定义变量
在这里插入图片描述
pst->age在计算机内部会被转化成(*pst). age
是->的含义,这也是一种硬性规定
所以pst->age等价于(*pst).age也等价于st. age

在这里插入图片描述
在这里插入图片描述
通过函数完成对结构体变量的输入和输出
例子:

#include<stdio.h>
#include<String.h>
struct Student{
	int age;
	char sex;
	char name [100];
}; //分号不能省

void InputStudent(struct Student *);
void OutputStudent(struct Student *);

int main(void){
	struct Student st; //15行
	
	InputStudent(&st); //对结构体变量输入
	OutputStudent(&st); //对结构体变量输出,可以发送st的地址也可以直接发送st的内容
	
	return 0;
}
void OutputStudent(struct Student *pst){
	printf("%d %c %s\n", pst->age, pst->sex, pst->name);
}

void InputStudent(struct Student * pstu){
	//pstu只占4个字节
	(*pstu).age = 10;
	strcpy(pstu->name, "张三");
	pstu->sex = 'F';
}

冒泡排序

#include<stdio.h>
#include<String.h>

void sort(int * a,int len){
	int i,j,temp;
	for(j=0;j<len-1;j++){//最后一组不用判断
		for(i=0;i<len-1-j;i++){//
			if(a[i]>a[i+1]){
				temp=a[i];
				a[i]=a[i+1];
				a[i+1]=temp;
			}	
		}
	}	
}

int main(void){
	
	int len = 5;
	
	int a[len]={1,44,344,4,5};
	
	sort(a,len);
	
	for(int i=0;i<len;i++){
		printf("a[%d]=%d\n",i,a[i]);
	}
	
	return 0;
}

在这里插入图片描述
代码:

//动态构造的案例
#include <stdio.h>
#include <malloc.h>

void Input(struct Student * Parr1,int len0);
void sort(struct Student * Parr2,int len2);
void Output(struct Student * Parr1,int len1);

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

//主调用函数
int main(void)
{
	int len;
	struct Student * pArr;
	struct Student t;

	printf("请输入学生的个数:\n");
	printf("len = "); 
	scanf("%d",&len);

	//动态构造一维数组 ,pArr代表的是数组 
	pArr = (struct Student *)malloc(len * sizeof(struct Student));

	//输入数据: 
	Input(pArr,len);
	
	//成绩排序 ,冒泡实现,比较的是成绩的大小,但是交换的是整体的数据的顺序 
	sort(pArr,len);


	printf("\n\n学生数据:\n"); 
	//输出数据: 
	Output(pArr,len);
}

//输入
void Input(struct Student * Parr1,int len0)
{//Parr1代表的就是数组 ,传入的本身就是指针变量
	for(int i=0;i<len0;i++)
	{
		printf("请输入第 %d 学生的数据:\n",i+1);//提示用户的输入

		printf("name = ");
		scanf("%s",Parr1[i].name);
		
		printf("age = ");
		scanf("%d",&Parr1[i].age);//scanf需要地址符号 & 
		
		printf("score = ");
		scanf("%f",&Parr1[i].score);
		printf("\n");
	}
}

//排序
void sort(struct Student * Parr2,int len2)
{
	struct Student t;
	for(int i=0;i<len2-1;i++)
	{
		for(int j=0;j<len2-1-i;j++)
		{
			if(Parr2[j].score > Parr2[j+1].score)//  大于>升序 小于<是降序
			{//比较成绩的大小
				t = Parr2[j];//互换的是整体,所以t 要定义为struct Student类型。否则数据不一致,无法赋值
				Parr2[j] = Parr2[j+1];
				Parr2[j+1] = t;
			}
		}
	}
}

//输出
void Output(struct Student * Parr1,int len1)
{
	for(int i=0;i<len1;i++)
	{
		printf("第 %d 学生的数据:\n",i+1);
		printf("name = %s ",Parr1[i].name);//name本来就是数组,数组名称内部存放的也刚好是第一个元素的地址,所以可以不用加取地址符号 &
		printf("age = %d ",Parr1[i].age);
		printf("score = %lf \n\n",Parr1[i].score);
	}	
}

弹幕评论:
name[100]这里已经把name定义成一个数组了,pArr[i].name就已经是地址了,所以不用&

枚举

在这里插入图片描述
把一个事物所有可能的取值一一列举出来
在这里插入图片描述
在这里插入图片描述

进制转换与补码

进制转换,只是简单了解一下,printf 的用法(进制转换)

.

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

链表

算法:

  • 通俗定义:
    解题的方法和步骤

  • 狭义定义:
    对存储数据的操作
    对不同的存储结构,要完成某一个功能所执行的操作是不一样
    比如:
    1.要输出数组中所有的元素的操作和
    2.要输出链表中所有元素的操作肯定是不一样的
    总结:
    算法是依附于存储结构的
    不同的存储结构,所执行的算法是不一样的

  • 广义定义:
    广义的算法也叫泛型
    无论数据是如何存储的,对该数据的操作都是一样的
    在这里插入图片描述
    无论数据是如何存储的,对该数据的操作都是一样的
    (先学java再回来看的 c ,看到这句话的时候,只想到一个词—精妙)
    在这里插入图片描述
    数组占的大内存是连续的,链表可以任意分割用小内存存储,但是每段内存都要多加一条指针
    在这里插入图片描述

  • 链表中的一些专业术语
    头指针:存放头结点的地址的指针变量;
    首节点:存放第一个有效数据的节点;
    尾节点:存放最后一个有效数据的节点;
    头结点:
    1.头结点的数据类型和首节点的类型一模一样;
    2.头结点是首节点前面的哪个节点;
    3.头结点并不存放有效数据;
    4.设置头结点的目的是为了方便对链表的操作;

只一个链表的长度,只需要知道其 头指针 就行了
头指针–》头节点–》首节点–》。。。–》尾节点

.
定义了一个可以存放该类型前面节点地址的指针

老师的源码截图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
老师的源码:只有添加功能

#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
struct Node
{
	int data; //数据域
	struct Node * pNext; //指针域
}; //NODE等价于struct Node PNODE等价于struct Node *

//函数声明
struct Node * create_list (void);
void traverse_list (struct Node *);

int main(void)
{
	struct Node * pHead = NULL;//等价于struct Node * pHead =NULL;
	pHead = create_list(); //create_list()功能:创建一个非循环单链表,
	traverse_list(pHead);
	return 0;
}


struct Node * create_list(void)
{
	int len; //用来夺放有效节点的个数
	int i;
	int val; //用来临时存放用户输入的结点的值
	//分配了一个不春放有效数据的头结点
	struct Node * pHead = (struct Node *)malloc(sizeof(struct Node));
	if (NULL == pHead)
	{
		printf("分配失败,程序终止!\n");
		exit(-1);
	}
	struct Node * pTail = pHead;
	pTail->pNext = NULL;
	
	printf("请输入爬需要生成的链表节点的个数: len = ");
	scanf("%d", &len);

	for (i=0;i < len;++i)
	{
		printf ("请输入第%d个节点的值: ", i+1);
		scanf ("%d", &val);
		struct Node * pNew = (struct Node *)malloc(sizeof(struct Node));
		if (NULL == pNew)
		{
			printf ("分配失败,程序终止!\n");
			exit(-1);
		}
		pNew->data = val;
		pTail->pNext =pNew;
		pNew->pNext = NULL;
		pTail = pNew;
	}
	return pHead;
}

void traverse_list(struct Node * pHead)
{
	struct Node * p = pHead->pNext;
	while(NULL != p)
	{
		printf("%d ", p->data);
		p=p->pNext;
	}
	printf("\n");
	return;
}

最后一点知识

内存本身是由操作系统控制的
在这里插入图片描述

注意:释放内存不是把分配给程序的内存清零

在这里插入图片描述
内存地址是内存单元的编号

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜里的雨

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值