专业课C语言(郝斌)

第一章 C语言概述

1.为什么要学习C语言
程序设计语言的发展:机器语言-汇编语言-高级语言。

2.怎样学习C语言
优点
代码量小 速度快 功能强大
缺点
危险性高 开发周期长 可移植性不强

3.学习的目标
4.常见的一些问题
5.课程计划
6.举例子:一元二次方程

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<math.h>
int main() {
	double a, b, c;
	scanf("%lf %lf %lf", &a, &b, &c);//double的格式控制符是%lf,%f是float的控制符,需要注意。
	double delta = b * b - 4 * a * c;
	double x1, x2;
	if (delta > 0) {
		x1 = (-b - sqrt(delta)) / (2 * a);
		x2 = (-b + sqrt(delta)) / (2 * a);
		printf("x1=%lf x2=%lf", x1, x2);
	}
	else if (delta == 0) {
		x1 = (-b ) / (2 * a);
		x2 = x1;
		printf("x1=x2=%lf", x1);
	}
	else {
		printf("方程无解!");
	}
	return 0;
}

第二章 C语言编程预备知识

1. cpu 内存条 硬盘 显卡 主板 显示器之间的关系?
答:文件一开始是存储在硬盘,把文件从硬盘调用到内存条,cpu再处理内存条中的文件,图像在显示器上输出,声音在声卡上输出,主板将中间设备组织在一起,显卡是电脑进行数模信号转换的设备,承担输出显示图形的任务。

2. HelloWorld程序是如何运行的?
答:编译链接生成.exe可执行文件,操作系统调用cpu执行exe文件。

3. 什么是数据类型?
答:
基本数据类型
整型:int(4)+short int(2)+long int(8),只能存放整数
浮点型:单精度:float(4) 双精度:double(8)
字符:char(1)

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

4. 什么是变量?
答: int i;i=3;3最终是存放在内存中,程序终止之后,3所占的空间被释放。变量是一个字母,对应内存中一个空闲的单元。
变量的本质是内存中的一段存储空间。

5. cpu vs 内存条 操作系统之间的关联

6. 变量为什么必须初始化?
答:初始化就是赋值的意思。

7. 如何定义变量?
答:数据类型 变量名=赋值;
等价于
数据类型 变量名;
变量名=赋值;

8. 什么是进制?
答:
十进制逢十进一
二进制逢二进一
C语言规定八进制前加0,十六进制加0x
%d十进制输出
%x或%X表示十六进制输出
%o表示八进制输出

9. 常量在C语言中是如何表示的?
答:整数、浮点数、字符
字符:单引号
字符串:双引号

10.常量是以什么样的二进制代码 存储在计算机中?
答:整数是以补码的形式转换为二进制代码存储在计算机中的。
实数是以IEEE754标准转换为二进制代码存储在计算机中的。
字符的本质实际也是与整数的存储方式相同。

11. 代码规范化
答:代码要成对敲
换行:定义变量,对变量进行操作,输出值

代码的可读性增强
使程序更不容易出错

12. 什么是字节
答:字节是存储数据的单位,并且是硬件所能访问的最小单位。
字节=8位Bit
1k=1024字节
1M=1024k
1G=1024M

13. 不同类型数据之间相互赋值的问题

14. 什么是ASCII
答:ASCII不是一个值,而是一种规定,规定了不同的字符是用哪个整数去表示。
A----65
B----66
a----97

  1. 字符的存储【字符本质上与整数的存储方式相同】

第三章 基础知识

基本的输入输出函数的用法
答:
printf() :将变量的内容输出到显示器

为什么需要输出控制符:
答:1. 01组成的代码可以表示数据也可以表示指令
2. 如果01代码表示的是数据的话,那么同样的01代码组合以不同的输出格式输出就会有不同的输出结果。

#x 16进制输出

scanf():
用法一:scanf(“输入控制符”,输入参数)
功能:将从键盘输入的字符转换为输入控制符所规定的格式的数据,然后存入以输入参数的值为地址的变量中。

用法二:含有非输入控制符
scanf(“m%d”.&i);//m123为正确输入
非输入控制符必须原样输入!!!

用法三:一次给多个变量赋值

用法四:如何避免错误输入

while((ch=getchar())!='\n')
    continue;//把前面所有非法输入干掉

如何高质量输入?
答:使用scanf之前最好先输出提示信息,最好不要使用非输入控制符,尤其不要使用\n,应该编写代码对用户的非法输入做处理。

运算符

  1. 算数运算符

  2. 关系运算符

  3. 逻辑运算符
    &&:同时为真结果才为真
    ||:有一个为真即为真

  4. 赋值运算符
    优先级别:算术>关系>逻辑>赋值,最好加括号来表示优先级高低。

取余运算符的对象必须是整数,除法运算符的对象只要有一个是浮点数,商就是浮点数。(2022.8.30)

第四章 流程控制

  1. 什么是流程控制?
    答:程序代码执行的顺序

  2. 流程控制的分类
    顺序执行
    选择执行
    循环执行

选择:

定义:某些代码可能执行,也可能不执行,有选择地执行某些代码。

  1. if最简单的用法
    答:if(表达式) 语句
    表达式为真,语句执行,为假,不执行。

  2. if的范围问题
    答:默认只能控制一个语句的执行;
    用大括号可以控制多条语句。

  3. if…else…的用法

  4. if…else if…else的用法

  5. C语言对真假的处理
    答:非零为真。

  6. 举例,求分数的等级

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
	float score;

	printf("请输入考试成绩: ");
	scanf("%f", &score);

	if (score > 100)
		printf("这是做梦!\n");
	else if (score >= 90)
		printf("A\n");
	else if (score >= 80)
		printf("B\n");
	else if (score >= 70)
		printf("C\n");
	else if (score >= 60)
		printf("D\n");
	else if (score >= 0)
		printf("不及格!\n");
	else
		printf("输入数据错误!");

	return 0;
}
  1. 举例 互换两个数字
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
//目的:互换两个数字
int main() {
	int i = 3;
	int j = 5;

	int tmp;

	tmp = i;
	i = j;
	j = tmp;

	printf("i=%d j=%d\n", i, j);
	return 0;
}



  1. 举例:对任意三个数字进行排序
//目的:对任意三个数字进行排序
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
	float a, b, c,t;
	printf("请依次输入a b c: ");
	scanf("%f %f %f", &a, &b, &c);

	//方法二:
	if (a > b) {
		t = a;
		a = b;
		b = t;
	}

	if (a > c) {
		t = a;
		a = c;
		c = t;
	}

	if (b > c) {
		t = b;
		b = c;
		c = t;
	}
	
	printf("%f %f %f", a, b, c);

	/*方法一:
	(a > b) {
		if (c > a)
			printf("%f %f %f", b, a, c);
		else if (c > b)
			printf("%f %f %f", b, c, a);
		else
			printf("%f %f %f", c, b, a);
	}
	else {
		if (c > b)
			printf("%f %f %f", a, b, c);
		else if (c > a)
			printf("%f %f %f", a, c, b);
		else
			printf("%f %f %f", c, a, b);
	}*/
	return 0;
}

如何看懂一个程序?
答:1.流程; 2.每个语句的功能; 3.试数(2022.8.31)

  1. if解析
    空语句

第五章 循环

定义:某些代码会被重复执行
分类:
for
while
do…while

举例:1/n求和

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
	int i;
	float sum = 0.0;

	for (i = 1; i <= 100; i++) {
		sum = sum + 1.0 / i;
	}

	printf("%f", sum);
	return 0;
}

浮点数的存储所带来的问题:
答:float和double都不能保证可以精确的存储一个小数.
举例:有一个浮点型变量x,如何判断x的值是否为0

if(x和一个非常小的值相减)

if(|x-0.000001|<=0.000001)
	是零;
else
	不是零;

为什么循环更新的变量不能定义为浮点型?
答:不精确.

举例:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
	/*求1 - 100之间的奇数之和;
	求1到100之间的奇数个数;
	求1到100之间的奇数的平均值;
	求1到100之间奇数之和, 再求1到100之间偶数之和;*/

	int sum = 0,sum1=0,sum2;
	int total = 0;
	float average;
	for (int i = 1; i <= 100; i++) {
		sum += i;
		if (i % 2 != 0) {
			sum1 += i;
			total++;
		}		
	}

	average = (float)sum1 / total;
	sum2 = sum - sum1;

	printf("%d %d %f %d\n", sum1, total, average, sum2);

	return 0;
}

自增和自减:
++i:整体表达式的值是i加1之后的值;
i++:整体表达式的值是i加1之前的值.

为什么会出现自增?
答:代码更精炼,速度更快.

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

三目运算符:

A?B:C;

逗号表达式:
答:从左向右执行,最终表达式的值是最后一项的值。

while

与for相互比较:

//求和
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
	int sum = 0;
	int i = 1;
	while(i < 101) {
		sum += i;
		i++;
	}
	printf("%d", sum);
	return 0;
}

举例:输入一个数,如果是回文数,返回yes,否则返回no;

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
	int val,m;
	int sum = 0;
	scanf("%d", &val);
	m = val;
	while (m) {
		sum = sum * 10 + m % 10;
		m = m / 10;
	}

	if (sum == val)
		printf("yes!\n");
	else
		printf("no!\n");

	return 0;
}

举例:斐波那契序列:(2022-9-3)

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
	int f1 = 1, f2 = 2, f3;
	int n;
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		if (i == 1) {
			f3 = f1;
			printf("%d\n", f3);
		}
			
		if (i == 2) {
			f3 = f2;
			printf("%d\n", f3);
		}
			
		if (i >= 3) {
			f3 = f1 + f2;
			f1 = f2;
			f2 = f3;
			printf("%d\n", f3);
		}
	}
	
	return 0;
}

do…while

主要用于人机交互。

do{

}while(表达式);
表达式成立进入循环。

举例:一元二次方程

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<math.h>
int main() {

	double a, b, c;
	double delta;
	double x1, x2;
	char ch;

	do {
		scanf("%lf %lf %lf", &a, &b, &c);
		delta = b * b - 4 * a * c;
		if (delta > 0) {
			x1 = (-b + sqrt(delta)) / (2 * a);
			x1 = (-b - sqrt(delta)) / (2 * a);
			printf("x1=%lf x2=%lf", x1, x2);
		}
		else if (delta == 0) {
			x1 = -b / (2 * a);
			x2 = x1;
			printf("x1=%lf x2=%lf", x1, x2);
		}
		else{
			printf("方程无解!");
		}
		printf("是否继续(y|n):\n");
		scanf(" %c", &ch);//%c前面必须有一个空格
	} while ('y'==ch);
	
	return 0;
}

switch

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
	printf("请输入楼层:");
	int val;
	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;
	}
}

break&continue

break:

  1. 用于循环则终止循环.
  2. 用于switch则终止switch.
  3. break不能直接用于if,除非if为循环的一部分.
  4. 在多层循环中,break只能终止最近的一层循环.

continue:
用于跳过本次循环余下的语句.

第六章 数组

为什么需要数组?
答:为了解决大量同类型数据的存储和使用问题,为了模拟现实世界。

数组的分类?
答:一维数组:
怎样定义一维数组:

  1. 为n个变量连续分配存储空间
  2. 所有的变量数据类型必须相同
  3. 所有变量所占的字节大小必须相等。

一维数组名代表第一个元素的地址。

二维数组:

多维数组:
答:不存在,因为内存是线性一维的。
n维数组可以当作每个元素是n-1维数组的一维数组。

第七章 函数

为什么需要函数?
答:避免了重复性操作,有利于程序的模块化,

什么叫函数?
答:逻辑上:能够完成特定功能的独立的代码块。
物理上:能够接收数据,能够对接受的数据,能够将数据的处理结果返回。
总结:函数是一个工具,它是为了解决大量类似问题而设计的,函数可以当作一个黑匣子。

如何定义函数?
答:函数的返回值 函数名(形参){ 函数的执行体}

  • 函数定义的本质是详细描述函数之所以能够实现某个特定功能的具体方法。
  • return 表达式。返回值,用于终止被调函数,向主调函数返回表达式的值;如果表达式的值为空,则只终止函数,不向被调函数返回任何值。
  • 函数返回值的类型也称为函数的类型,因为如果函数名前的返回值类型与return类型不同则最终以函数类型为准。

函数的分类?
答:有参函数和无参函数;有返回值和无返回值;库函数和用户自定义函数;普通函数和主函数。

一个程序有且必须只有一个主函数,主函数可以调用普通函数,普通函数不能调用主函数,普通函数可以相互调用,主函数是程序入口,也是程序的出口

举例:素数

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

bool IsPrime(int val) {
	int i;

	for (i = 2; i < val; i++) {
		if (val % i == 0)
			break;
	}
	if (i == val)
		return true;
	else
		return false;
}

int main() {
	int val;
	
	scanf("%d", &val);
	if (IsPrime(val))
		printf("Yes!\n");
	else
		printf("No!\n");

	return 0;
}

函数前置声明:

  1. 告诉编译器即将可能出现的若干个字母代表的是一个函数
  2. 告诉编译器即将可能出现的若干字母所代表的函数的形参和返回值的具体情况
  3. 函数声明是一个语句,末尾必须加分号。
  4. 对库函数的声明是通过#include<>

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

如何在开发中设计合理的函数来解决实际问题?
答:一个函数的功能尽量独立,单一;多学习,多模仿牛人的代码。

函数是C语言的基本单位。

常用的系统函数
答:

double sqrt(double x);//求x的平方根
int abs(int x)//求x的绝对值
double fabs(double x)//求x的绝对值

专题
递归

变量的作用域和存储方式?
答:按作用域分:
全局变量:在所有函数外部定义的变量。

局部变量:在一个函数内部定义的变量或者函数的形参。

变量名冲突时,局部变量将全局变量屏蔽。

按变量的存储方式分:
静态变量
自动变量
寄存器变量

第八章 指针

指针就是地址,地址就是指针。
地址就是内存单元的编号。
指针变量是存放地址的变量。
指针和指针变量是两个不同的概念。
要注意:通常我们叙述时会把指针变量简述为指针,实际他们含义并不一样。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
	int* p;//p是变量的名字,int*表示p变量存放的是int类型型变量的地址
	int i = 3;
	int j;

	//p = &i;//ok
	//p = i;//error,因为类型不一致,p只能存放int类型变量的地址,不能存放int类型的值

	p = &i;
	/*
		p保存了i的地址,因此p指向i;
		p不是i,i也不是p,更准确的说;修改p的值不影响i的值,修改i的值也不影响p的值
		如果一个指针变量指向了某个普通变量,则*指针变量就完全等同于普通变量
		例子:
			如果p是个指针变量,并且p存放了普通变量i的地址,则p指向普通变量i
			*p就完全等同于i
			(或者说,在所有出现*p的地方都可以替换成i,在所有出现i的地方都可以替换成*p)
			
			*p就是以p的内容为地址的变量
	*/
	j = *p;//等价于j=i
	printf("i=%d,j=%d", i, j);

	return 0;
}

指针的重要性:

表示一些复杂的数据结构
快速的传递数据
使函数返回一个以上的值
能直接访问硬件
能够方便的处理字符串
是理解面向对象语言中引用的基础。

指针的定义

地址:
答:内存单元的编号,从零开始的非负整数。
范围:4G

指针
答:指针就是地址,地址就是指针。
指针变量是存放内存单元编号的变量,或者说指针变量就是就是存放地址的变量。
指针和指针变量是两个不同的概念。
但要注意:通常我们叙述时,会把指针变量简称指针,但他们是两个不同的概念。
指针的本质就是一个操作受限的非负整数。

指针的分类

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

//不能完成互换
void swap1(int a, int b) {
	int t;
	t = a;
	a = b;
	b = t;

	return;
}

//不能完成互换
void swap2(int* p, int* q) {
	int* t;//t必须是int*,不能是int
	t = p;
	p = q;
	q = t;

	return;
}

//可以互换
void swap3(int* p, int* q) {
	int t;//如果要互换*p和*q的值,则t必须定义成int,不能定义成int*
	t = *p;
	*p = *q;
	*q = t;

	return;
}

int main() {
	int a=3;
	int b=5;

	swap1(a, b);
	

	printf("a=%d,b=%d\n", a, b);
	//swap2(*a, *b); //error, 
	//swap2(a, b);// 也是错误的,类型不兼容

	swap2(&a, &b);
	printf("a=%d,b=%d\n", a, b);

	swap3(&a, &b);
	printf("a=%d,b=%d\n", a, b);
	return 0;
}
  1. 基本类型指针

答:指针运算符: * 的含义:定义指针变量指针运算符,该运算符放在已经定义好的指针变量前面;
如果p是一个已经定义好的指针变量,则*p表示以p的内容为地址的变量

如何通过被调函数修改主调函数普通变量的值?

答:1.实参必须为该普通变量的地址。
2.形参必须为指针变量。
在被调函数中通过*形参名可以修改主调函数相关变量的值。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

//不能返回
int f(int i, int j) {
	return 100;
	return 200;
}

void g(int* p, int* q) {
	*p = 1;
	*q = 2;
}
int main(){
	int a = 3, b = 5;
	a = f(a, b);
	b = f(a, b);
	printf("a=%d b=%d\n", a, b);

	g(&a, &b);
	printf("a=%d b=%d\n", a, b);

	return 0;
}
  1. 指针和数组

指针和一维数组
一维数组名:它存放的是一维数组第一个元素的地址。
下标和指针的关系:如果p是个指针变量,则p[i]永远等价于 *(p+i)

确定一个一维数组需要几个参数?
答:2个,数组名(数组第一个元素的地址)和数组元素个数

指针变量的运算:

答:指针变量只能相减(两个指针变量指向同一连续空间中的不同存储单元时)。

一个指针变量到底占几个字节?

答:假设p指向char类型的变量(1个字节)
假设q指向int类型的变量(4个字节)
假设r指向double类型的变量(8个字节)
p,q,r本身都是占4个字节

总结:
一个指针变量,无论它所指向的变量占几个字节,该指针变量本身只占四个字节。
一个变量的地址使用该变量首字节的地址表示

指针和二维数组

  1. 指针和函数
  2. 指针和结构体
  3. 多级指针

专题:动态内存分配

传统数组的缺点:

  1. 数组的长度必须事先制定,且只能是常整数,不能是变量。
  2. 传统形式定义的数组,该数组的内存程序员无法手动释放。数组一旦定义,系统为该数组分配的存储空间就会一直存在,除非数组所在的函数运行结束。
    在一个函数运行期间,系统为该函数中数组所分配空间会一直存在,直到函数运行完毕,数组的空间才会被释放。
  3. 数组的长度一旦定义就不能更改。
  4. A函数定义的数组,在A函数运行期间可以被其它函数使用,但A函数运行完毕之后,A函数中的数组将无法被其它函数使用

为什么需要动态内存分配?

答:动态数组很好的解决了传统数组的缺陷。

举例

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<malloc.h>

int main() {
	int i = 5;
	int* p = (int*)malloc(4);//7行
	/*
	1. 使用malloc函数,必须添加malloc.h头文件
	2. malloc函数只有一个形参,并且是整数
	3. 4表示请求系统为本程序分配4个字节
	4. malloc只能返回第一个字节的地址
	5. 第7行分配了8个字节,p占4个字节,p所指向的内存也占4个字节
	6. p本身所占的内存是静态分配的,p所指向的内存是动态分配的
	*/

	return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<malloc.h>
void f(int *q) {
	*q = 200;
	//free(q);
}
//将p的值改为200
int main() {
	int* p = (int*)malloc(sizeof(int));
	*p = 10;

	printf("%d\n", *p);//10
	f(p);

	printf("%d\n", *p);//200

	return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<malloc.h>

int main() {
	int len;
	int* pArr;

	printf("请输入元素个数: ");
	scanf("%d",&len);
	pArr = (int *)malloc(4 * len);

	for (int i = 0; i < len; ++i)
		scanf("%d", &pArr[i]);

	for (int i = 0; i < len; ++i)
		printf("%d ", pArr[i]);

	free(pArr);

	for (int i = 0; i < len; ++i)
		printf("%d ", pArr[i]);
	return 0;
}

静态内存和动态内存的比较?

答:静态内存由系统自动分配,由系统自动释放。
静态内存是栈分配的。
动态内存是由程序员手动分配,手动释放。
动态内存是在堆分配的。

跨函数适用内存的问题?

静态内存不能夸函数使用:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<malloc.h>

void f(int** q) {
	int i = 5;
	/*
	*q等价于p q和**q都不等价于p
	*q=i;//error 因为*q=i:等价于p=i,这样写是错误的
	*/

	*q = &i;//p=&i
}
int main() {
	int* p; 
	f(&p);
	printf("%d\n", *p);
	return 0;
}

动态内存可以跨函数使用:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<malloc.h>

void f(int** q) {
	*q = (int*)malloc(sizeof(int));
	//等价于p=(int*)malloc(sizeof(int));
	**q = 5;//*p=5;

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

第九章 结构体

  1. 为什么需要结构体?
    答:为了表示一些复杂的事物,而普通的基本数据类型无法满足需求.

  2. 什么叫结构体?
    答:把一些基本数据类型组合在一起形成的一个新的复合数据类型,这个叫做结构体.

  3. 如何定义结构体?
    答:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

//第一种方式
struct Student1 {
	int age;
	float score;
	char sex;
};

//第二种方式
struct Student2 {
	int age;
	float score;
	char sex;
}st2;

//第三种方式
struct  {
	int age;
	float score;
	char sex;
}st3;

int main() {

	return 0;
}
  1. 怎样使用结构体变量?
    赋值如何初始化?
    答:定义的同时可以整体赋值;如果定义之后,则只能单个的赋初值。
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

//第一种方式
struct Student1 {
	int age;
	float score;
	char sex;
};


int main() {
	struct Student1 st = {80,66.6,'F'};//初始化 定义的同时赋值
	struct Student1 st2;
	st2.age = 10;
	st2.score = 88;
	st2.sex = 'F';

	printf("%d %f %c\n", st.age, st.score, st.sex);
	printf("%d %f %c\n", st2.age, st2.score, st2.sex);

	return 0;
}

如何去除结构体变量中的每一个成员?
答:1.结构体变量名.成员名
2.指针变量名->成员名

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

//第一种方式
struct Student1 {
	int age;
	float score;
	char sex;
};


int main() {
	struct Student1 st = {80,66.6,'F'};//初始化 定义的同时赋值
	struct Student1* pst = &st;//&st不能写成st

	pst->age = 88;
	printf("%d %f %c\n", st.age, st.score, st.sex);

	st.age = 10;
	printf("%d %f %c\n", st.age, st.score, st.sex);
	

	return 0;
}

pst->age 在计算机内部会被转换成 (*pst).age,所以 pst->age 等价于 (*pst).age 也等价于 st.age

结构体变量的运算
结构体变量和结构体变量指针作为函数参数传递问题
动态构造存放学生信息的结构体数组
6.

冒泡排序

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

void sort(int* pArr, int len) {
	for (int i = 0; i < len; i++) {
		for (int j = 0; j < len - i-1; j++) {
			if (pArr[j] > pArr[j + 1]) {
				int t = pArr[j];
				pArr[j] = pArr[j + 1];
				pArr[j + 1] = t;
			}
		}
	}
}
int main() {
	int a[6] = { 2,7,3,-1,2,4 };
	sort(a, 6);
	for (int i = 0; i < 6; i++) {
		printf("%d ", a[i]);
	}

	return 0;
}

举例 学生成绩系统

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<malloc.h>

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

	int len;
	struct Student* pArr;
	printf("请输入学生的个数:\n");
	scanf("%d", &len);
	pArr = (struct Student*)malloc(sizeof(struct Student) * len);

	for (int i = 0; i < len; i++) {
		printf("请输入第%d个学生的信息:\n",i + 1);
		printf("age= ");
		scanf("%d", &pArr[i].age);

		printf("name= ");
		scanf("%s", pArr[i].name);

		printf("score= ");
		scanf("%f", &pArr[i].score);
	}

	struct Student t;
	for (int i = 0; i < len; i++) {
		for (int j = 0; j < len - i - 1; j++) {
			if (pArr[j].score > pArr[j + 1].score) {
				 t = pArr[j];
				pArr[j] = pArr[j + 1];
				pArr[j + 1] = t;
			}
		}
	}

	for (int i = 0; i < len; i++) {
		printf("\n请输出第%d个学生的信息:\n", i + 1);
		printf("age= %d\n", pArr[i].age);
		printf("name= %s\n", pArr[i].name);
		printf("score= %f\n",pArr[i].score);
	}

	return 0;
}

枚举

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>

enum WeekDay
{
	Monday,Tuesday,Wednesday,Thursday,Friday,Saturnday,Sunday
};

int main() {

	enum WeekDay day;

	return 0;
}

进制转换

补码

已知十进制求二进制?

答:求正整数的二进制:除2取余,直至商为零,余数倒序排序。

求负整数的二进制:先求与该负数相对应的正整数的二进制代码,然后将所有位数取反,末位加1,不够位数时,左边补1。
零的二进制:全零

已知二进制求十进制?

答:如果首位是0,则表明是正整数,按普通方法来求。
如果首位是1,则表明是负整数:将所有位数取反,末尾加1,所得数字就是该负数的绝对值。
零对应零。

0000 00000
0000 00011
0111 1111127
1000 0000-128
1000 0001-17
1111 1111-1

一个int类型的变量所能存储的数字十六进制表示范围:7FFFFFFF-80000000

第十章 链表

算法

通俗的定义:解题的方法和步骤
狭义的算法:对存储数据的操作 ,对不同的存储结构,要完成某一个功能所执行的操作不一样。
广义的算法:广义的算法也叫泛型,

数组:

优点:存取速度快
缺点:需要一个连续的很大的内存,插入和删除元素的效率很低

链表:

优点:插入删除元素效率高,不需要一个很大的内存。
缺点:查找元素效率低。

位运算符

&:转换为二进制按位与
&&:整体与,结果只能是0或者1
|:按位或
||:逻辑或
~:按位取反
^:异或,相同为0,不同为1
<<:按位左移,右边补0,相当于乘以2,

期末试卷

1.什么叫分配内存,什么叫释放内存?

答:操作系统把某一块内存空间的使用权限分配给程序叫分配内存;把分配给该程序的内存空间使用权利收回,该程序不能再使用这块内存空间。

2.变量为什么得初始化?

答:不初始化,变量就是垃圾值。

3.详细的说明系统如何执行int i=5;这个语句的?

答:软件请求操作系统为i分配存储空间,操作系统在内存中寻找一块空闲区域当作i来使用,软件将i与这块空闲区域关联起来,以后对i的操作就是对这块区域的操作,把5存储到i所关联的内存区域中。

4.C语言的基本类型

答:int long int, char ,float, double

5.请问long int ,char ,double ,float分别用射门输出?

答:%ld %c %lf %f

6.函数的优点是什么?

答:避免重复操作,有利于模块化。

7.谈谈函数的理解?

8.什么是地址,指针变量,指针,三者之间是什么关系?

答:地址是存储单元的编号,指针就是地址,指针和地址是同一个概念;
指针变量是存放内存单元的变量,指针变量和指针是两个完全不同的概念,只不过人们通常把指针变量简称为指针。

9.简述静态变量和动态变量的异同。

答:相同:都需要内存分配
不同:静态变量由系统自动分配与释放,程序员无法在运行过程中释放与分配,静态变量是在栈中分配的,函数终止后,静态变量的存储空间才会由内存自动释放。
动态变量由程序员手动分配内存与释放,在堆中分配,函数执行过程中可以分配与释放。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

太极生两鱼

要天天开心哦!

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

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

打赏作者

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

抵扣说明:

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

余额充值