2.12 #define定义宏和符号常量

(1)#define 定义符号常量(为了和变量区分,使用大写)


#define MAX 100
int main()
{int arr[MAX] = { 0 };  //定义的是常量,可以放在数组的下标中
}

(2)#define 定义宏

#define ADD(X,Y) ((X)+(Y))
//编程习惯,为了防止出错,把x和y分别加上括号,例如X是表达式
// ADD和(X,Y)之间没有空格
int main()
{int sum = ADD(3, 4);printf("%d\n", sum);
}//错误示例
#define ADD(X,Y) (X*Y)    //编程习惯,为了防止出错,把x和y分别加上括号 ADD和(X,Y)之间没有空格 int main()
{int multiply = ADD(3+5, 4);  //输出的是23,实际应该是32printf("%d\n", sum);
}

2.13内存的划分

从操作系统的角度对内存进行划分,可以分为

栈区:局部变量

堆区:动态分配内存

静态区:全局变量,静态变量

类似将国土面积,划分为一个个省市等,找到房间,需要找到房间的编号,即地址。把内存划分为一个个小的内存单元,访问内存单元需要提供地址,每个内存单元的编号就是内存单元的地址。计算机中的内存划分是以字节为单位的,即1Byte=8bit,每一个地址都对应一个内存单元,8个比特对应一个地址。

根据地址线的数量,计算机分为32位和64位。以32位操作系统为例,(包含32根物理的电线)计算机通电之后,电信号转为数字信号(正电1负电0),

数据类型(int ,char float)每次申请空间以字节为单位,所以1个内存单元代表1个字节,内存划分为一个个小的内存单元,一个内存单元的大小是一个字节,为了使用内存单元,对其进行编号,编号是通过地址线产生的二进制序列。

2.14指针

指针是用来存放地址的变量。在定义指针类型的时候,前面的*代表所定义的变量是一个指针,int 代表所指向的变量是一个整型变量

int main()
{int a = 100;int* p = &a; //取地址操作符//*p代表p是指针,前面的int代表p指向的是一个整型变量 a//
}

在定义时候使用*p代表的是指针,代表所指向变量的地址,在使用时候*p代表对地址的解引用,即得到所指向的变量。

int main()
{int a=100;int *p=&a; //定义指针,指向的是a的地址*p=20; //解引用指针,修改的是a的值printf("%d\n",a);return 0;
}

每个内存单元都有一个编号,就是地址。指针变量的大小由地址决定的,32位需要32个bit位存放,即4个字节,而与指向变量的类型无关。

int main()
{int a = 10;int* pa = &a;   //定义了一个指向a的指针pa//*pa 得到a的值 char c = 'a';char* pc = &c;float f = 2.13;float* pf = &f;double d = 3.22;double* pd = &d;printf("%d ", sizeof(pa));//4printf("%d ", sizeof(pc));//4printf("%d ", sizeof(pf));//4printf("%d ", sizeof(pd));//4
}

2.15结构体

C语言提供了一些内置的简单数据类型,但是并不能满足构造复杂对象的需求,例如人是复杂的对象(年龄,身高,身份证,性别等),不能用一个或者一种简单的数据类型进行表达。需要创建一个复杂类型即结构体类型,使得C语言有能力描述复杂类型。

struct Stu
{char name[20];int age;char sex[5];char id[15];}; // 一般的编辑器会提供,注意末尾的分号一定不能省int main()
{//汉字占两个字符,所以不可以使用''//创建并初始化结构体对象struct Stu s1 = { "张三",30,"男","340604" };//结构体对象使用.进行引用printf("name = %s age = %d sex=%s id = %s\n ", s1.name, s1.age, s1.sex, s1.id);//创建结构体指针,使用->访问结构体成员struct  Stu* ps = &s1;printf("name = %s age = %d sex=%s id = %s\n ", ps->name, ps->age, ps->sex, ps->id);printf("name = %s age = %d sex=%s id = %s\n ", (*ps).name,(*ps).age,(*ps).sex,(*ps).id);
}

2.16循环和分支

C语言中由一个分号;隔开的就是一条语句。

例如:1+2;

printf("hello world");

分支语句(选择结构)

(1) if (表达式)

语句;

(2) if (表达式)

语句1;

else

语句2;

(3)多分支

if(表达式1)

语句1;

else if(表达式2)

语句2;

else

语句3;

注意:《1》if后面的表达式没有分号,表达式结果为真(非0)则执行后面的语句

           《2》只能跟着一条语句,多条语句使用复合结构

int main()
{int score=10;scanf("%d",&score);if(score>60)    //输入的语句多于一条,使用复合语句{printf("输入的成绩大于60\n");printf("考试成绩合格\n");
}

    《3》else语句和最近的if配对,而不是和形式上对齐的if配对

int main()
{int score=0;scanf("%d",&score);if(score>60)   if(score>90)printf("输入的分数大于90,成绩良好\n");else                    //else语句和第二个if配对而不是和形式上对齐的第一个if配对printf("需要补考\n");   }

书写建议是多使用{}把逻辑的关系理清

int main()
{int score=0;scanf("%d",&score);if(score>60)   {if(score>90)printf("输入的分数大于90,成绩良好\n");}else                    //使用{}之后 ,第二个if语句成了第一个if语句的一部分,else和第一个if配对printf("需要补考\n");   }

《4》if后面的表达式包含多个判断条件时,例如

int main()
{int score=0;scanf("%d",&score);if(90<score<100)   //此种方式错误,进行关系判断的时候,得到的值为0或者1//假设输入的是91,则91>90得到的结果是1,再和100进行判断,即1<100结果为真//假设输入的是10,则10>90得到的结果是0,再和100进行判断,即0<100结果为真//所以需要使用逻辑运算符&&
//代码修改为if(score>90&&score<100)printf("成绩优异\n"); }

《5》if if else 和if else if  else的区别

在if if else语句的结构中,if都会被执行,如果下面这个程序输入的是99,则会输出两次

int main()
{int score = 0;scanf("%d", &score);if (score > 90)printf("恭喜您,考试成绩为%d\n",score);if(score>80)printf("还不错,考试成绩为%d\n",score);elseprintf("加把油,考试成绩为%d",score);}

在if else if语句的结构中,只有一个if会被执行,如果下面这个程序输入的是99,则会输出1次

int main()
{int score = 0;scanf("%d", &score);if (score > 90)printf("恭喜您,考试成绩为%d\n",score);else if(score>80)printf("还不错,考试成绩为%d\n",score);elseprintf("加把油,考试成绩为%d",score);}

return作为语句的结束标志,可以直接返回,即结束函数

2.17 switch语句

switch是一种分支语句,常用于处理多个分支的情况。例如输入每个星期对应的日期,如果使用if else语句,显得过于繁琐。

int main()
{int day = 0;scanf("%d", &day);if (1==day)printf("星期1\n");else if(2==day)printf("星期2\n");else if(3==day)printf("星期3\n");else if(4==day)printf("星期4\n");else if(5==day)printf("星期5\n");else if(6==day)printf("星期6\n");elseprintf("星期天\n");}

使用switch语句进行判断,

int main()
{int day = 0;scanf("%d", &day);switch(day){case 1:printf("星期1\n");break;case 2:printf("星期2\n");break;case 3:printf("星期3\n");break;case 4:printf("星期4\n");break;case 5:printf("星期5\n");break;case 6:printf("星期6\n");break;case 7:printf("星期7\n");break;}}

注意:《1》switch(整型表达式)建议定义为int ,short有时候会出现溢出的错误

           《2》case语句是分支,不是循环,不可以使用continue

           《3》使用break跳出当前的循环,如果没有break,case语句会顺序接着执行

           《4》switch中的语句是可以任意调换的

int main()
{int day = 0;scanf("%d", &day);switch(day){case 1:case 2:case 3:case 4:case 5:printf("工作日\n");break;case 6:case 7:printf("休息日\n");break;}}

只能在循环中使用continue,跳出此次循环的后面部分,进行下一次的循环,跳转到while语句的判断部分


//1 2 3 4 死循环
int main()
{int i = 1;while(i<=10){if(i==5){continue;}printf("%d ",i);i++;}}

如果是break,则跳出当前的循环


//1 2 3 4
int main()
{int i = 1;while(i<=10){if(i==5){break;}printf("%d ",i);i++;}}

在windows系统安装的vs2019使用ctrl+z作为EOF(文件结束标识符),getchar是从输入缓冲区中获取的一个字符,其函数原型是

int getchar( void ); 函数返回的是一个int型,因为字符在计算机中以整数的形式存储

int main()
{int ch = 0;while ((ch = getchar()) != EOF)putchar(ch);return 0;
}

scanf函数触发中断,程序等待用户输入,在输入\n后把缓冲区中的数据取出放到对应的地址中,getchar在输入缓冲区中读取到输入时候的\n,所以程序直接跳过。

int main()
{int ch = 0;char password[20] = { 0 };printf("请输入密码>:");scanf("%s", password);printf("请输入(Y/N);>");ch = getchar();if ('Y' == ch){printf("确认成功\n");}else{printf("放弃确认\n");}
}

修改方案一:此时可以获取一个\n,但是当scanf输入的数字类似 12 3 4 ,程序依然出错

int main()
{int ch = 0;char password[20] = { 0 };printf("请输入密码>:");scanf("%s", password);ch = getchar();//获取输入的\nprintf("请输入(Y/N);>");ch = getchar();if ('Y' == ch){printf("确认成功\n");}else{printf("放弃确认\n");}
}

修改方案二:使用scanf进行输入的时候以空白(空格,TAB,换行)作为输入结束的标识符

\n表示的时输入结束,真正被scanf读取的是第一个空白之前的数据

int main()
{int ch = 0;char password[20] = { 0 };printf("请输入密码>:");scanf("%s", password);while ((ch = getchar()) !='\n')   //使用scanf输入时,\n表示输入结束,所以当不是\n时//把输入的字符使用getchar()存储,表示的时输入结束,真正被scanf读取的是第一个空白之前的数据{}printf("请输入(Y/N);>");ch = getchar();if ('Y' == ch){printf("确认成功\n");}else{printf("放弃确认\n");}
}

2.18循环语句

while语句

int main()
{int i=0;  //初始化部分while(i<10)        //判断部分{printf("%d ",i);i+=2;    //调整部分}}

由于while语句三个部分不集中,为了解决这个问题引入for循环,

int main()
{for(i=0;i<10;i++)  //初始化;条件判断部分;调整部分;{if(i==5)continue;printf("%d ",i);}}
int main()
{for(i=0;i<10;i++)  //初始化;条件判断部分;调整部分;{if(i==5)break;printf("%d ",i);}}

不要随意省略表达式,否则会出现各种未知错误,出了错误学会自己调节

int main()
{int i = 0;int j = 0;int count = 1;for (i = 0; i < 10; i++){for (j = 0; j < 10; j++){printf("%d\n", count);count++;//循环100次}}
}

但是下面的代码仅仅执行20次,因为在第一次执行完j的循环之后,j=10,再次进行i=1的判断时,j的循环变量不满足条件,所以并不进入,但是此时i仍然需要增加。

int main()
{int i = 0;int j = 0;int count = 1;int count1= 1; for (; i < 10; i++){printf("%d\n", count1);for (; j < 10; j++){printf("%d\n", count);count++;//循环10次}}
}

如果判断条件为假,则一次也不执行。

int main()
{int i = 0;int k = 0;for (i=0,k=0; k=0; i++,k++){k++;}
}

任何表达式都是有值的,b=(a=3) 赋值符号是右结合性,a的值等于3。

int main()
{int i = 0;do{    if(i==5)continue;printf("%d ",i);i++;}while(i<=10);return 0;
}

全局变量:在所有函数之前定义的变量

局部变量:在函数内或者复合语句内部定义的变量

int main()
{int i = 0;                     //局部变量int j = 0;int count = 1;int count1= 1; for (; i < 10; i++){printf("%d\n", count1);for (; j < 10; j++){printf("%d\n", count);count++;//循环10次}}
}

局部变量实在执行该函数或复合语句时自动建立的,当该函数或者复合语句执行完毕后自动释放,所以在不同的函数或者复合语句中定义同名的局部变量,也不会相互干扰。

写代码都是进行累计的,不会写循环,先写一次,在考虑循环的环境

例子:查找数字

int main()
{int arr[] = { 1,2,3,4,5,6,7,8,9,0 };int n = 7;int i = 0;for (i = 0; i < 10; i++){if (arr[i] == n){printf("找到了:%d\n", i);break;}}if (i == 10){printf("找不到\n");}return 0;
}

使用srand我们规定只定义一次就可以,参数是unsigned int 类型

但是time返回的是time_t类型,所以需要类型转换

void game()
{int guess = 0;int ret = rand() % 100 + 1;while (1){printf("请输入猜测的数字:>");scanf("%d", &guess);if (guess > ret){printf("猜大了\n");}else if (guess < ret){printf("猜小了\n");}else{printf("恭喜你,猜对了\n");break;}}}
void menu()
{printf("*******************\n");printf("*****  0.exit *****\n");printf("*****  1.play******\n");printf("*******************\n");
}
int main()
{int input = 0;srand((unsigned int)time(NULL));do {menu();scanf("%d", &input);switch (input) {case 0:printf("游戏结束\n");break;case 1:game();break;default:printf("输入错误\n");break;}} while (input);}

system("shutdown -s -t 60"); 关机

system("shutdown -a");取消关机    等价于在cmd中输入

if else if 和if if的区别,如果一个进去了,if else if就不在进去,对于if 和if来说,一个进去了,另一个还需要再次进入判断

函数

使用函数,

1.提高了开发的效率

2.提供统一的标准。

函数分为两种,库函数和自定义函数。

库函数:把一些常用的功能用C语言封装成了函数,放在C语言的库函数中

#include<stdio.h>
#include<math.h>int main()
{char arr1[]="hello bit";
char arr2[20]={0};strcpy(arr2,arr1);
printf("%s\n",arr2);}
#include<stdio.h>
#include<math.h>int main()
{char arr1[]="hello bit";memset(arr,'*',5);printf("%s\n",arr);}

函数内部想要改变函数外部的值,使用指针传递。

void Swap(int a,int b)  //当实参传给形参的时候,形参是实参的临时拷贝
{int tmp=a;a=b;b=tmp;}
void Swap1(int *a,int *b)//当实参传给形参的时候,形参是实参的临时拷贝
{int tmp=a;a=b;b=tmp;}int main()
{int x=0,y=0;scanf("%d%d",&x,&y);printf("交换前:x=%d y=%d\n",x,y);Swap(x,y);Swap1(&x,&y);return 0;
}

自定义函数:根据用户需求定义的函数。和库函数一样,有函数名,返回值类型和函数参数。

函数的组成:

ret_type fun_name(para1,*)   返回类型  函数名  函数参数

{

statement;

}

函数参数(实参):

真实传递给函数的参数,即实参,实参可以是常量,变量,表达式,函数等。无论实参是何种类型的量,在进行函数调用时,它们都必须要有确定的值,以便把这些值传递给形参。

int a=10;
int max=get_max(1,2);
max=get_max(1,a);
max=get_max(1+4,get_max(2,3));

形式参数(形参):

形式参数是指函数名后括号中的变量,因为形式参数只有在函数被调用的过程中实例化,调用完成后自动销毁,只在函数中有效。

形参可以是变量,表达式和函数调用

int a=10;
int max=get_max(1,a); //变量
max = get_max(1+4,get_max(2,3)); //表达式,函数

不需要返回值的时候,前面一定要加上void,有些编辑器返回的默认值是int

一般不在函数内部进行打印,因为这样就相当于在一个函数内部生成了两个功能。例如程序员A仅需要得到max的值,所以函数功能不完善,建议一个函数仅仅实现一个功能。代码的复用性高。让函数的功能更加独立。

void get_max(int a,int b)
{int max=(a>b)?(a):(b);printf("%d\n",max); //实现了打印的功能
}
int get_max(int a,int b)
{int max=(a>b)?(a):(b);return max;    //为了保证函数代码的独立性
}int main()
{int a=0;int b=0;scanf("%d%d",&a,&b);int m=get_max(a,b);printf("%d\n",m);//实现了打印的功能
}

最害怕的是没开始就放弃,第一篇博客的约定是什么?

void new_line()
{printf("hehe\n");
}void three_line()
{int i = 0;for (i = 0;i < 3; i++){new_line();// 函数可以嵌套使用}printf("hehe\n");
}void Add(int *p)
{void test()    //函数不可以嵌套定义{}*p=*p+1;}

链式访问

把一个函数的返回值作为另外一个函数的参数

int main()
{int len=strlen("abcdef");printf("%d\n",len);//链式访问printf("%d\n",strlen("abcdef"));// 4321 print返回打印的字符的个数printf("%d",printf("%d",printf("%d",43)));// 4322 换行也是一个字符printf("%d",printf("%d\n",printf("%d",43)));
}

程序从main函数开始执行,


int Add(int x,int y)
{int z=x+y;return z;
}int main()
{int a=10;int b=20;int ret=Add(a,b);printf("%d\n",ret);
}

如果想把Add函数写在主函数的后面,则需要在main之前进行函数声明,即

int Add(int x,int y);
int main()
{int a=10;int b=20;int ret=Add(a,b);printf("%d\n",ret);
}
int Add(int x,int y)
{int z=x+y;return z;
}

C语言初阶,知识点简介(2)相关推荐

  1. C语言初阶知识点思维导图(超大图片、超级详细版)

  2. C语言初阶(18) | 数组详解

    目录 1.数组的定义 2.一维数组 2.1一维数组的格式 2.2一维数组的初始化 2.3一维数组的使用 2.4一维数组再内存中的存储 3.二维数组 3.1二维数组的创建和初始化 3.2二维数组的使用 ...

  3. C语言初阶_初识C语言(1)

    凡是过往,皆为序章 期末考试结束了,真是感慨良多啊...... C语言编程题大家都做对了多少呢? 不管怎么样,都已经过去了.不管你学得怎么样,都可以在接下来的时间里,我们一起重新回顾一遍C语言初阶的知 ...

  4. 五十分钟带你看遍C语言初阶语法(总纲)

    C语言初阶语法(总纲) 此篇博客包含了前面C语言所有的基础语法,写这一期的博客不仅是为了记录自己的学习成果也是为了让更多的朋友能学到对自己有用的知识,如果总有一个知识点帮助到了你,给卑微博主点点关注加 ...

  5. C语言初阶——6.进制

    C语言初阶--6.进制 1. 进制 百度百科: 进制也就是进位计数制,是人为定义的带进位的计数方法,对于任何一种进制-X进制,就表示每一位置上的数运算时都是逢X进一位. 十进制是逢十进一,十六进制是逢 ...

  6. C语言初阶作业题-数组

    C语言初阶作业题-数组 一.选择题 1.关于一维数组初始化,下面哪个定义是错误的?( ) A.int arr[10] = {1,2,3,4,5,6}; B.int arr[] = {1,2,3,4,5 ...

  7. C语言初阶——5.字符串

    C语言初阶--5.字符串 1. 字符串操作 1.1 字符串遍历 可以通过数组方式遍历字符串. char* str="Hello World"; for(int i = 0;'\0' ...

  8. C语言初阶第三篇:换我心,为你心,始知C语言 从C语言选择语句到循环语句保姆教学来喽

    换我心,为你心,始知C语言 老铁们,咱们上一篇文章把字符串的知识点给过了一遍,今天就要开始真正的程序语句的学习了,也就是选择语句和循环语句,今天的内容比较简单,所以写的也不多,废话不多说,咱们开始吧! ...

  9. C语言初阶总结 v1

    目录 C 基础1⭐ 数据类型 计算机中的单位 常量与变量 字符串/转意字符/ 注释 C 基础2⭐ 判断语句 函数与数组 C语言操作符 C语言关键字 C语言定义宏与关键字 初始指针 ⭐⭐ 指针基础 拓展 ...

最新文章

  1. 一堂C++课玩转rpm包的制作
  2. hdu5375(格雷码问题+简单DP)
  3. 1042 字符统计 (20 分)(c语言)
  4. .NET技术之美-网络编程
  5. jenkins docker 自动部署 构建_jenkins+docker+vue项目的自动部署环境
  6. 前端学习(3240):react生命周期forceUpdate
  7. 知识图谱论文阅读(二十一)【SIGIR2019】NGCF: Neural Graph Collaborative Filtering
  8. 【模板】非旋Treap
  9. 开除“野狗”式程序员,团队的效率提高了
  10. 7、边沿触发-D型触发器
  11. Beaver‘s triple(乘法三元组)-秘密共享的乘法计算
  12. 写论文引用参考文献详细教程
  13. 《三桃演义》第二回:返航,火星人柯里昂
  14. 联想小新13pro锐龙版网卡_联想小新Pro 13标压锐龙版评测:比香还香 买就完了
  15. 面试系列-1 大厂面试幂等性
  16. 机器学习实战——疫情数据分析与预测
  17. 【影评】海贼王:855
  18. MySQL从删库到跑路(0):序章
  19. 对初创公司进行估值的九种方法
  20. 免费计算机应用毕业论文,计算机应用毕业论文 5000字

热门文章

  1. ijkplayer ffmpeg x264 android 编译
  2. Python3爬虫(一):Python的入门学习以及Python网络爬虫的初步认识
  3. 如何使用cubic快速重装linux系统
  4. Python3 中的nonlocal用法
  5. Java如何创建文件?java创建文件流程图文详解!
  6. 一种基于Myers‘diff算法的文本比对工具的实现
  7. Linux系统学习攻略带你学会Linux
  8. php 项目 jwt,JWT 在项目中的实际使用
  9. Android拼接Byte数组
  10. JAVA基础面试题目