一、刷一遍b站黑马程序员c语言二级视频
1.重要例子
1.1 for循环与if结合的水仙花试题
打印从100-999之间各个位数(个位十位 百位)的立方和等于本身的数为水仙花数:
#include<stdio.h>
int main(){
int a;
int b;
int c;
int i;
for(i=100;i<=999;i++)
{
a = i/100;//百位
b= i/10%10;//十位
c= i%10;//个位
if((a*a*a+b*b*b+c*c*c) == i)
{
printf("%d是水仙花数\n\r",i);
}
}
return 0;
}
1.2 for循环与continue结合的例子
打印0-100之间的所有偶数:
#include<stdio.h>
//打印0-100之间的所有偶数
int main(){
int i;
for(i=0;i<=100;i++)
{
if(i%2!=0){
continue;
i++;
}
else
{
printf("%d\n\r",i);
}
}
return 0;
}
1.3 两层循环嵌套例子
打印99乘法表:
#include<stdio.h>
//循环嵌套,打印99乘法口诀
int main(){
int i;
int j;
for(i=1;i<=9;i++)
{
for(j=1;j<=9;j++){
if(i>=j){
printf("%d*%d=%d",j,i,i*j);
}
}
printf("\n");
}
return 0;
}
1.4 数组和for循环if判断语句联系的例子
冒泡排序:
#include<stdio.h>
//冒泡排序,数组相关知识
//思想:假设一共有10个数字放在数组中,想将它们的顺序排为降序,可以通过9次将10个数排序完成
//内层第一次通过9次将最大值放在最前面,第2次通过8次将第二大的值放在第二位置,以此类推,10-1-i个数进行操作
int main(){
int a[10] = {1,9,78,96,4,7,0,45,8,34};
int temp;//临时变量,用于互换位置用
int i,j;
for(i=0;i<=10-1;i++){
for(j=0;j<=10-1-i;j++){
if(a[j]<=a[j+1])
{
temp = a[j];
a[j]=a[j+1];
a[j+1] =temp;
}
}
}
for(i=0;i<=10-1;i++){
printf("%d\n",a[i]);
}
return 0;
}
1.5 二维数组的定义
#include<stdio.h>
//二维数组
int main(){
int a[4][3] = {
{88,89,100},
{36,42,59},
{60,67,34},
{88,89,90}
};
int i,j;//外层循环控制行,内层循环控制列
int sum ;
for(i=0;i<4;i++){
printf("第%d行的元素数据为:",i);
for(j=0;j<3;j++){
printf("%d ",a[i][j]);
}
printf("\n");
}
//假设每行的数据是四名同学的成绩
//先来求出每一行的和
sum = 0;
for(i=0;i<4;i++){
for(j=0;j<3;j++){
sum=sum + a[i][j];//对于内层循环而言,目前外层i对应的行是固定的
}
printf("第%d个同学的总成绩为:%d\n",i,sum);
sum=0;
}
//再来求出每一列的和
//对于求列和的过程而言,应该吧3放在外面,即保持列的值不变
for(i=0;i<3;i++){
for(j=0;j<4;j++){
sum+=a[i][j];//对于内层循环而言,目前外层i对应的列是固定的
}
printf("第%d科的总成绩为:%d\n",i,sum);
sum = 0;
}
return 0;
}
1.6 字符串的比较
本质上来说字符串本身就是一种特殊的字符数组,以‘\0’结尾,因此可以通过字符数组的方式来比较。
#include<stdio.h>
//字符串的比较
//注意:字符串是一种特殊的字符数组,双引号定义,以\0结尾
int main(){
char arr1[]="hello world";
char arr2[] = "heool world";
int i=0;
while(arr1[i]==arr2[i]){
if(arr1[i]=='\0'){
printf("两个字符串相同\n");
return 0;
}
i++;
}
printf("两个字符串不相同\n");
return 0;
}
1.7 随机数的产生
想产生随机数分为三步:
导入time.h stdlib.h头文件
将time函数当前系统时间作为srand()函数的随机数种子参数,通过rand()函数取模获得特定范围的随机数。
#include<time.h>
#include<stdlib.h>
#include<stdio.h>
//随机数,常考
int main(){
//创建随机数种子
srand((unsigned int)time(NULL));//time()函数是获取当前系统时间,并将其返回值作为随机数种子
printf("%d\n",rand()%10);//0-9之间的随机数
return 0;
}
1.8 函数定义与递归
函数递归的调用思想:每次调用递归函数的过程其实就是一个压栈和出栈的问题,先将递归函数满足条件的情况下不断压栈存储,等不满足条件递归条件以后不断出栈。
典型的例子就是求解n的阶乘:
//函数递归
//定义一个递归函数,用来求阶乘
#include<stdio.h>
//定义递归函数,每次调用会不断压栈,到最后在出栈,并不断向外释放空间
int refun(int a){//a为形参
//定义局部变量,用于接收返回值
int value;
if(a==1){
value = 1;
}
else
{
value = a*refun(a-1);
}
return value;
}
int main(){
int a= 5;
int b = 0;
b = refun(a);
printf("%d!==%d\n",a,b);
return 0;
}
1.9 将指针作为函数参数传递,达到改变实参值的目的
#include<stdio.h>
//指针
//重要应用,在调用函数的时候,通过值传递并不能够改变实参的内容,因为两个函数是定义在两个存储区域
//例如:
void swap(int a,int b){
int temp = a;
a=b;
b=temp;
}
int main01(){
int a=10;
int b=20;
swap(a,b);
printf("%d,%d\n",a,b);//a,b的值并不能改变,该子函数内部打印的话可以,因为这是两次定义的a b定义在不同的存储区上面
return 0;
}
//将指针作为函数的参数便可以解决这个问题
void swap(int* a,int* b){
int temp = *a;
*a=*b;
*b=temp;
}
int main(){
int a=10;
int b=20;
swap(&a,&b);
printf("%d,%d\n",a,b);//a,b的值并不能改变,该子函数内部打印的话可以,因为这是两次定义的a b定义在不同的存储区上面
return 0;
}
1.10 将数组名作为函数参数传入例子
#include<stdio.h>
//将数组名作为函数的参数来传递,因为数组名本身就是一个地址,即可以作为指针变量中存放的值
//以冒泡排序为例
void BubbleSort(int* a,int length){//冒泡排序需要两个参数,一个数数组,另一个是数组的长度
int i;
int j;
int temp;
for(i=0;i<length-1;i++){
for(j=0;j<length-1-i;j++){
if(a[j]>a[j+1]){
temp = a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
}
int main(){
int i;
int c[10]={1,2,8,4,7,0,67,29,5,7};
BubbleSort(c,10);
for(i=0;i<10;i++)
{
printf("%d\n",c[i]);
}
return 0;
}
1.11 结构体的定义与成员访问
#include<stdio.h>
#include<string.h>
//结构体与共用体
//大题重点内容
//用typedef说明一个新类型:发生在编译阶段
//例如:typedef unsigned int ui;//定义一个无符号整型数据类型,叫做ui
//结构体类型数据的定义与成员的引用
/*
1.结构体定义:用来将多个不同类型的数据组合在一起
2.格式:
结构体 结构体名称{
结构体成员列表;
};
3.结构体变量的引用方式为:结构体名.成员
4.结构体本身也是一种数据类型,因此引出结构体数组这个定义
*/
struct stu{
int id;//编号
char name[21];//姓名
char sex;
int age;
int score;
char address[51];
};
int main(){
//按照结构体成员列表的顺序依次初始化数据,取名为ss 注意这里的struct stu为一个整体的结构体名
struct stu ss={1001,"libin",'F',18,18,100,"beijing"};
//打印结构体信息
printf("biaohao:%d\n",ss.id);
//修改结构体成员信息方式
ss.id=1003;
//注意,针对于数组而言ss.name是数组名,不能通过上面的方式直接赋值,这里可以通过strcpy函数来将一块内存中的内容拷贝到这里
//字符串拷贝
strcpy(ss.name,"Big_Bin");
//定义结构体数组
struct stu a[3]={
{1001,"1","M",20,99,"1"},
{1002,"1","M",20,99,"1"},
{1003,"1","M",20,99,"1"}
};
//通过结构体数组[下表].成员找到对应的内容
printf("%s\n",a[1].name);
return 0;
}
1.12 结构体数组排序(重要)
//结构体排序:根据结构体中某一项成员的内容,对整个结构体进行排序
//题目要求:通过键盘输入的方式获取学生信息,信息为:编号 姓名 年龄 成绩,然后根据年龄对结构体数组进行排序
typedef struct str{
int id;
char name[21];
int age;
int store;
}student;//将结构体名自定义为student
int main(){
//定义结构体数组
student a[3];
int i;
student temp;
for(i=0;i<3;i++){
scanf("%d-%s-%d-%d",&a[0].id,a[i].name,&a[i].age,&a[i].store);//依次输入信息
}
int j;
for(i=0;i<3-1;i++){
for(j=0;j<3-1-i;j++){
if(a[j].age>a[j+1].age)
{
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
for(i=0;i<3;i++){
printf("编号:%d\t",a[i].id);
printf("姓名:%s\t",a[i].name);
printf("年龄:%d\t",a[i].age);
}
return 0;
}
1.13 共用体(联合体)union
这种构造的类型与结构体的用法基本一致,最主要的区别在于它的提出是为了节约内存空间,它是一个能在同一个存储空间存储不同类型数据的类型,但每一个瞬时只有一种起作用,变量中起作用的成员是最后一次存放的成员。共用体变量的地址和她的各成员地址都是同一个地址。
1.14 链表
数组每次需要分配一块连续的存储区域,而链表无需一次性分配一块连续的存储区域,只需要分配n块节点的存储区域,通过指针来建立关系。
1.15 文件的打开与关闭(获取文件的地址)
#include<stdio.h>
#include<stdlib.h>
//文件操作
/*
1.文件指针:定义一个指针变量指向一个文件,这个指针称为文件指针 File *
2.文件打开与关闭
File * fopen(const char * filename,const char *mode);(路径,打开模式) mode:r只读 w写 a以追加方式打开
注意:路径用/斜杠
*/
int main(){
FILE * fp;//创建文件指针
fp = fopen("D:/c/erji/a.txt","r");//返回值若为NULL,说明读取失败
if(fp==NULL){
printf("open is failed\n");
return -1;
}
printf("opened\n%p\n",fp);
//关闭文件
fclose(fp);
return 0;
}
1.16 文件的读写
//通过fgetc(fp)读取文件中的内容
int main(){
FILE * fp;//创建文件指针
char ch;
fp = fopen("D:/c/erji/a.txt","r");//返回值若为NULL,说明读取失败
if(fp==NULL){
printf("open is failed\n");
return -1;
}
printf("opened\n%p\n",fp);
while((ch=fgetc(fp))!=EOF){//文件的读写,每次读取一个字符fgetc(fp)
printf("%c",ch);
}
//关闭文件
fclose(fp);
return 0;
}
//通过fputs(&ch,fp)向文件中写入字符
//向文件中写字符
int main(){
FILE * fp;
char ch ='A';
fp = fopen("D:/c/erji/b.txt","w");
if(fp==NULL){
printf("open is failed\n");
return -1;
}
fputs(&ch,fp);//向文件中写入字符
fclose(fp);//关闭文件
return 0;
}
二、公共知识总结
1.公共基础部分
计算机系统基础:
1.要使用外部存储器,应先将其调入(内存储器);
2.I/O方式中使计算机系统并行工作程度最高的是(通道);
3.处于阻塞状态的进程,当阻塞原因解除后即进入就绪状态;
4.在CPU执行一条指令的过程中(至少)占用一个机器周期;
5.机器周期的同步标准是(CPU访问存储器一次所需要的时间);
6.当一个进程在运行过程中释放了系统资源后要调用(唤醒进程原语);
7.进程调度只负责对CPU进行分配;
8.过程控制系统属于(实时系统);
9.允许多个联机用户同时使用一台计算机系统进行计算的操作系统属于(分时操作系统);
10.补码的符号位取反即是偏移码;
11.虚拟存储器是对(主存)的拓展;
12.通常说的计算机主机包括(中央处理器和主存储器);
13.如果指令中的地址码部分直接给出了操作数,则称为(立即寻址);
给出操作数的地址,成为(间接寻址);
如果指令中的地址码部分给出了操作数在存储器中地址的寻址方式为(直接寻址);
操作数的地址隐含在指令的操作码或者某个寄存器中的寻址方式是(隐含寻址);
14.虚拟存储器的空间大小取决于(计算机的访存能力);
15.请求分页或请求分段式存储管理需要采用虚拟管理系统;
16.计算机中的缓冲技术用于(提高主机和设备交换信息的速度);
17.并发性的另一个重要属性是动态性;
18.如果一个进程在运行过程中暂定,将进入(阻塞状态);
19.一个正在运行的进程由于所申请的资源得不到满足要调用(阻塞进程原语);
20.机器数补吗的符号位取反即是偏移码;
21.操作系统的功能主要有:处理器管理、存储管理、设备管理、文件管理和用户接口;
22.进程一旦被创建,即进入就绪状态;
23.在多道程序的环境下,程序和计算机执行程序将不再一 一对应;
24.分时操作系统具有以下几个特点:交互性、独立性、及时性和同时性;
25.过程控制中的系统一般使用(实时操作系统);
26.进程存在的唯一标志是数据结构(PCB);
数据结构与算法:
1.为了降低算法的空间复杂度,要求算法尽量采用原地工作。所谓原地工作指:(执行算法所使用的额外空间固定);
2.没有根结点或者没有叶子结点的数据结构一定是非线性结构;
具有两个根结点的数据结构一定是非线性的;
3.循环队列和循环链表都是线性结构;
4.