赞
踩
Hello,大家好!!!这里是小周为您带来的呕心沥血之作------C语言秘籍!!
C语言秘籍分为初阶和高阶两部!!跟着小周学定会让你C语言功力大成,称霸武林,话不多说,马上开讲!!!!!
C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。
尽管C语言提供了许多低级处理的功能,但仍然保持着良好跨平台的特性,以一个标准规格写出的C语言程序可在许多电脑平台上进行编译,甚至包含一些嵌入式处理器(单片机或称MCU)以及超级电脑等作业平台。
二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异,由美国国家标准局为C语言制定了一套完整的美国国家标准语法,称为ANSI C,作为C语言最初的标准。 [1] 目前2011年12月8日,国际标准化组织(ISO)和国际电工委员会(IEC)发布的C11标准是C语言的第三个官方标准,也是C语言的最新标准,该标准更好的支持了汉字函数名和汉字标识符,一定程度上实现了汉字编程。
C语言是一门面向过程的计算机编程语言,与C++,Java等面向对象的编程语言有所不同。 其编译器主要有Clang、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等。
Clang是一个由Apple主导编写,基于LLVM的C/C++/Objective-C编译器
GCC是linux平台使用的编译器,是由GUN开发的
在C语言秘籍中我使用的是VS2019社区版编译器(免费的,已经够我们学习使用了),用这个软件为大家详细讲解
在我的讲解中,所有相关代码都在CODE-C-2024: 这里是你的编程好友小周的代码仓库!欢迎你的到来,我们一起学编程吧!!!!!中,欢迎大家访问!
1、下载好以后,点击这个紫色图标
2、点击创建新项目
3、点击空项目,点击下一步
4、修改项目名称,项目存放位置,点击创建
5、进入VS2019
如果你跟着我的步骤但没有看到项目的话,点击视图-解决方案资源管理器即可
如果你在以后的操作过程中,不小心关掉了解决方案资源管理器
也可以按照上述办法就可以恢复
另外这个框框其实是可以挪动的,根据你的习惯来,用鼠标拖动他,屏幕上的鼠标箭头对准中心对应的位置,就能将解决方案资源管理器挪到你想挪的位置
C语言程序中,有两种文件
.h header 头文件
.c 源文件
点击新建项以后
如果名称写成.cpp的话,编译器会按照C++的语法编译,不可以随便乱写像test.d test.h test.x等等!!!
test.h只有在头文件中,后缀才可以这么写,才是可行的
添加好以后,默认就给我们打开了,我们就可以书写代码了
在这里先写出来最简单的几句代码,然后详细为大家讲解
注:写好的C语言代码是文本信息,这些代码不能直接运行起来
.c 要经过 编译+链接 最后生成 可执行程序
test.c test.exe
我们使用的VS2019是集成开发环境,什么是集成开发环境?
在VS2019里面写代码称为编辑功能,可以使用VS2019实现编译、链接、运行、调试等功能,集成开发环境将这些功能集成在一起
编译+链接+运行
快捷键:1.Ctrl + F5
2.Ctrl + Fn + F5(可能有一些电脑用Ctrl + F5不行,这时用第二种方式)
3.菜单中:[调试]->[开始执行不调试]
那我们说是否像小周说的生成了.exe文件呢?我们一起来看看,找到我们之前存放项目的路径
我们发现确实生成了!这个就是hello world代码被编译链接后生成的可执行程序
而控制台打印hello world运行起来的就是.exe文件
1.代码一般是从main函数开始写(主函数)
标准写法如下
- int main()
- { //函数体
- return 0;
- }
int是整型 (函数的返回类型),main是函数名,代码执行到最后,return 0意思是返回的是0,而0是整数,返回类型就是int
{
是函数体
}
2、我们运行发现屏幕上打印出了左面对应的代码
这时我们点击F10,我们会发现有一个黄色的箭头
它既没有出现在第7行,也没有出现在第14行,而是出现在了第9行(main函数里的第一行)
我们接着按两次F10,我们会发现
不断按F10,箭头在往下走,同时右面会同时打印出对应的内容
3、那么100-500 行代码,如何执行呢?
不难得出,程序是从main函数的第一行开始执行的,所以C语言代码中得有main函数-程序的入口
那可以有好多个main函数吗?
答案是不可以!它报错了!此时因为你写的代码,走火入魔,导致电脑懵b了,两个入口,电脑也不知道该走哪一个,就出现问题了
所以有且仅有一个main函数
1.一个工程中可以有多个.c文件
2.但是多个.c文件中只能有一个main函数
补充1:大家在学习编程时候肯定或多或少会阅读许多书籍,如果你看的书中main函数是这么写的,那么请注意,赶紧扔掉,这本书太古老了,不适合你这种有天赋的人修行
- void main()//这种不推荐
- {
-
- }
这两种是可以的
- //这种写法也有 - 这个是可以的
- int main(void)//void在这里表示main函数不接受任何参数
- {
- return 0;
- }
-
- //这种方式以后再研究
- int main(int argc,char* argv[])
- {
- return 0;
- }
补充2:
printf - 库函数 - C语言编译器提供的一个现成的函数,可以直接使用 - 功能:在屏幕上打印数据 printf 的使用,也得打招呼(引用头文件 stdio.h) 没有会报错,对应库函数的使用要包含对应的头文件,因为是C语言提供的不是你自己编写的
在之前的例子中
- #include<stdio.h>
- int main()
- {
- printf("hello world");//"hello world"是一个字符串
- return 0;
- }
“ ”双引号引起来的就是字符串,也可以在“ ”中间打印中文,\n是换行符号,如果打印多个,想一行有一个,就可以加上\n,这样打印出来就是一行一个
- #include<stdio.h>
- int main()
- {
- printf("hello world\n");
- printf("hello world\n");
- return 0;
- }
小测验:难度⭐
写个代码,在屏幕上打印:I like 编程!
评论区和码云见答案哦!!!大家多动手,编程能力提升的越快哦!!!
理解:计算机语言 - 写程序 - 解决生活中问题 必须有能力来描述生活中的问题!
解决网上购物的问题:网上商城,商品,名字,价格,分类
价格 20 整数 整型类型int表示
25.5 小数 浮点型 float / double
C语言提供了哪些类型呢?这些类型用来表示某一些数据的格式或类型
- char //字符数据类型 a b c n q @ !
- 整型
- short //短整型
- int //整形
- long //长整型
- long long //更长的整形
- 浮点型
- float //单精度浮点数
- double //双精度浮点数
- C99中引用了 _Bool 布尔类型
- long double
- #include <stdio.h>
- int main()
- {
- //字符类型
- char ch = 'a';
- //整型
- int age = 20;
- //短整型
- short num = 10;
- //long
- //long long
-
- //单精度浮点型
- float weight = 55.5;
- //双精度浮点型
- double d = 0.0;
- return 0;
- }

我们在日常生活中会发现,存放任何东西都需要对应的空间,这里存放数据也不例外,那么每种类型的大小是多少呢?
- //每种数据类型的大小
- #include<stdio.h>
- int main()
- {
- printf("hehe\n");
- printf("bite\n");
- printf("%d\n",100);//打印一个整数,%d是对应的以十进制的方式打印一个整数
- //sizeof - 关键字 - 操作符 - 计算类型或者变量所占空间的大小
- //sizeof的单位是什么?- 字节byte
- printf("%d\n",sizeof(char)); //1个字节
- printf("%d\n",sizeof(short)); //2个字节
- printf("%d\n",sizeof(int)); //4个字节
- printf("%d\n",sizeof(long)); //4个字节
- printf("%d\n",sizeof(long long)); //8个字节
- printf("%d\n",sizeof(float)); //4个字节
- printf("%d\n",sizeof(double)); //8个字节
- return 0;
- }
- C语言标准:
- sizeof(long)>=sizeof(int)

运行得出
这里给大家介绍一下计算机中的单位:
bit - 比特位 - 存放一个二进制位的
1Byte - 1字节 = 8bit
1Kb = 1024 Byte
1Mb = 1024 Kb
1Gb = 1024 Mb
1Tb = 1024 Gb
1Pb = 1024 Tb
计算机中识别的是二进制 1/0 10进制的数字每一位可以是0-9之间的任何一个数,那么二进制的数字·每一位是0或者1这两个数
在二进制中存放一个0或者1的空间需要一个比特位---1bit
在这里用一个1表示1bit,,那么下图就是1Byte=8bit
char ch = 'w';
上述代码是什么意思呢?
我们创建了一个char类型的名字叫ch的变量,变量的创建是一定要在内存中开辟空间的
其实内存里存的是W的ASCII码值!不是W这个字符
小测验:难度⭐
创建一个整型的变量,命名随意,赋值为20
评论区和码云见答案哦!!!大家多动手,编程能力提升的越快哦!!!
在生活中有些值是不变的(比如:圆周率,性别,身份证号码,血型等等)
有些值是变的(比如:年龄,体重,薪资)
在C语言中,常量表示不变的值,变量表示变的值
- #include <stdio.h>
- int main()
- {
- //类型 变量名;
- //类型 变量名 = 初始值;
-
- int age;
- int age2 = 20;
- //55.5 小数直接写出来,编译器默认是double类型的
- //55.5f 这个时候就是float类型
- float weight = 55.5f;
- double weight2 = 88.5;
- return 0;
- }
只能由字母(包括大写和小写)、数字和下划线(_)组成
不能以数字开头
长度不能超过63个字符
变量名中区分大小写
变量名不能使用关键字
- int main()
- {
- int _2b;
- int _2B;
- //int char; error
- //变量名要起的有意义
- return 0;
- }
局部变量
全局变量
- #include <stdio.h>
- //全局变量
- int a = 100;
-
- int main()
- {
- //局部变量 - { }内部定义的
- //当局部变量和全局变量名字冲突的情况下,局部优先
- //不建议把全局变量和局部变量的名字写成一样的
- int a = 10;
- int num = 10;
- printf("%d\n", num);//10
- num = 20;
- printf("%d\n", num);//20
- return 0;
- }

在这里我们要与数学等式做区分,3+5=8,是从左往右算的,而num=10则是把10赋值给num变量
例子:写一个代码求2个整数的和
- #include <stdio.h>
- int main()
- {
- //写一个代码,求2个整数的和
- int num1 = 0;
- int num2 = 0;
- int sum = 0;
- //输入2个整数的值
- //&num1 - 取出num1的地址
- //& 取地址操作符
- scanf("%d %d", &num1, &num2);//10 20
- //scanf函数双引号部分是指定了输入的格式,后面部分要给两个地址
- sum = num1 + num2;
-
- //打印
- printf("%d\n", sum);
-
- return 0;
- }
- //scanf函数是输入函数,printf函数是输出函数
- //scanf_s函数 - 是vs编译提供的,不是C语言标准规定的

那么会有很多同学在这里运行出现错误,这是为什么呢?那小周为什么没出错呢?
那是因为
我在第一行这里有这句代码
那没有它会出什么错误呢?
这是什么意思呢?
微软的编译器认为scanf不安全,建议使用scanf_s,但是scanf_s函数是VS提供的,只有VS编译器认识,其他的编译器是不认识的,如果你的代码中使用了scanf_s函数,这样就不跨平台了,建议初学时候还是使用scanf
那我们怎么解决呢?
错误说明里面已经告诉我们了,To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.把 _CRT_SECURE_NO_WARNINGS这句代码复制,然后来到第一行把图片中的代码敲进去
即可,就可以解决这个问题
那难道我们每次使用scanf时都要这么做吗?感觉特别麻烦呀,接下来小周给大家介绍一个一劳永逸的方法!大家也注意到了,小周创建一个空项目以后,第一行自动就有这个代码!其实非常简单
在VS的安装路径下,存在一个文件:newc++file.cpp 的文件,为了方便大家以后的工作,我在这里为大家推荐一个很方便的软件叫Everything
这是一个很便捷的快捷搜索软件
然后右键打开路径
然后再次右键,推荐大家都以记事本的方式打开,因为有些同学的电脑无法直接打开
然后把第一行的代码打进去,保存就可以了
如果说你保存不了,那么将它复制到桌面,然后打开修改保存,最后拖动到原先的位置替换即可,不能搞丢哦!这样以后新建的.c/.cpp的文件中默认就有这个代码了
补充:scanf和printf都是C语言的库函数,是C语言编译器提供的现成的函数,可以直接使用
scanf的作用是输入数据,数据从键盘读到内存中
printf的作用是输出数据,数据从内存打印(输出)到屏幕上
%c-字符 %d-整型 %s-字符串 %f-float %lf-double %p-地址的打印
1.定义
作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域
理解:哪里起作用哪里就是他的作用域
在这里我们成功打印出了a的值,因为a的作用域在中间的{ }中
那如果我们将printf语句分离出来呢?
我们发现报错了,因为此时a的作用域在中间的{ }里面,执行到26行时,a变量已经失效了,所以才会报错说a时未声明的标识符
我们把a挪出中间的{ }
我们发现a的范围变成主函数对应的{ }了,所以成功输出a的值
局部变量是{ }之内的变量且{ }之内如果嵌套{ }那么要注意,小范围的变量失效,大范围的变量就用不了了
全局变量是大括号以外的变量
那么全局变量呢?
我们发现,其实在语法允许的情况下,在任何地方这个变量a都可以使用
我们再来看一个例子,我们再创建一个add.c的源文件并运行
所以
局部变量的作用域是变量所在的局部范围。
全局变量的作用域是整个工程。
全局变量不安全,尽可能不使用
1、定义
变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段
局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
全局变量的生命周期是:整个程序的生命周期。
执行到//...时离开了局部变量a b c的作用域,后续操作也不会利用a b c,还占用空间,那又有什么用呢?理论上讲离开中间的{ }以后存在也没有用了,也没必要存在了
那全局变量呢?
全局变量在主函数范围内都是可以使用的,意味着在整个程序生命周期中全局变量都存在,所以全局变量的生命周期是:整个程序的生命周期。
C语言中的常量和变量的定义的形式有所差异。
C语言中的常量分为以下以下几种:
字面常量
- int main()
- {
- 3.14;
- 10;
- 'a';//字符
- "abcdef";//字符串
- }
const 修饰的常变量
- int main()
- {
- int num = 10;
- num = 20;
- printf("%d\n", num);
- return 0;
- }
上面的代码结果显示此时num是变量,值可变
- int main()
- {
- const int num = 10;
- num = 20;//此时再对num做出数值的改变也没有用,并且是错误的,不能直接修改
- printf("%d\n", num);
- }
在定义的变量前加关键字const那么num就变成常变量 - 具有常属性(不能被改变的属性)
不是常量,是不变的量
num还是变量但是值一直都是10,不再变化
验证代码:
- int main()
- {
- int a = 10;
- int arr[a] = { 0 };//a是变量,这里是不行的,会报错
- const int n = 10;
- int arr2[n] = { 0 };//经过const修饰的n虽然值不会发生改变,但依然是变量,这里是不行的,会报错
- }
#define 定义的标识符常量
- #define MAX 10000 //define定义出来的 MAX 值是10000
- int main()
- {
- //MAX = 200; //这么写是错误的,定义好后不可以在这里给他赋新的值
- int n = MAX;
- printf("n = %d\n", n);
- return 0;
- }
枚举常量
1.定义:可以一一列举的常量
在生活中有些值是可以一一列举的 性别:男、女、保密 三原色:red、green、blue
2.关键字:enum
以性别为例:
- enum Sex
- {
- //这种枚举类型的变量Sex的未来可能取值
- //下面三个值就是枚举常量(在这个例子中只能是这三种)
- MALE,
- FEMALE,
- SECRET
- };
- int main()
- {
- enum Sex s = MALE;//枚举的可能取值是给枚举类型赋值的
- //MALE = 3;//错的,不能这样改枚举变量的值
- //在这里打印出来
- printf("%d\n", MALE);
- printf("%d\n", FEMALE);
- printf("%d\n", SECRET);
- return 0;
- }

枚举常量是常量,默认值从0开始,每次增加1
如果是下面这种情况
- enum Sex
- {
- //这种枚举类型的变量Sex的未来可能取值
- //下面三个值就是枚举常量(在这个例子中只能是这三种),但是常量的初始值是可以改的
- MALE=3,
- FEMALE=6,
- SECRET=9
- };
- int main()
- {
- enum Sex s = MALE;
- //MALE = 3;//错的,不能这样改枚举变量的值
- //在这里打印出来
- printf("%d\n", MALE);
- printf("%d\n", FEMALE);
- printf("%d\n", SECRET);
- return 0;
- }

结果会有所不同
字符串其实就是一串字符,字符串用双引号来表示
字符-你在键盘上敲出的任何东西,那我们怎么表示字符呢?用单引号 'a' '1' ' '
- int main()
- {
- char c;
- c;
- return 0;
- }
如果不用单引号来表示,我们如何区分字符c和变量c呢?
"Hello World"
这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符串
注:字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串内容。
- int main()
- {
- //"abcdef";
- //char ch1 = 'a';
- //char ch2 = 'b';
- //char ch3 = 'c';//有些麻烦
- char ch[] = {'a', 'b', 'c', 'd', 'e', 'f'};//字符数组 - 数组是一组相同类型的元素
- char ch2[] = "abcdef";
- //上一行[]中并没有表明数组中有多少个元素,此时就会根据后面的字符串来初始化这个数组
- printf("%s\n", ch);
- printf("%s\n", ch2);
-
- return 0;
- }
我们调试上述代码(按F10),然后按照图片步骤就可以打卡监视窗口,把要调试的ch数组ch2数组名称输入即可
我们可以发现字符串在结尾的位置隐藏了一个\0的字符
我们运行程序,得到
我在这里画一个内存图方便大家理解
在内存中,我们不知道ch和ch2数组前面和后面是什么,我们用%s来打印字符串%s是打印字符串的意思
我们打印字符串会发现ch数组出现了奇怪的字和空格ch2数组并没有出现这种情况
printf以%s打印字符串的时候,就从我们给的地址开始打印,一直打印到遇到\0停止
注:字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串内容。
小测验:难度⭐⭐
那如果我们在ch数组中加入'\0'呢(放在字符a的前面,放在字符f的后面分别尝试)?打印出来的结果是什么呢?这个任务就交给你了,评论区见答案哦!
我们通过另外一种方式来证明上面的结论---求字符串长度
- #include <string.h>
-
- int main()
- {
- char ch1[] = { 'a', 'b', 'c'};//[a][b][c]
- char ch2[] = "abc"; //[a][b][c][\0]
-
- int len1 = strlen(ch1);//strlen是用来求字符串长度的库函数,就是从给定的地址向后数字符
- //直到遇到\0结束,\0不统计在内
- printf("%d\n", len1);
-
- int len2 = strlen(ch2);
- printf("%d\n", len2);
-
- return 0;
- }

这里面的15是随机值,因为我们只知道ch1和ch2里的内容,并不知道它们在内存中前后是什么,所以每个人电脑的值可能与我的不一样
如果我们在ch1数组中加入'\0'会发生什么呢?如上图所示,我们发现结果是3,又能充分证明:字符串的结束标志是一个 \0
在这里先看一个例子,想正确在屏幕上输出(are you ok??)该怎么做呢?
- int main()
- {
- printf("(are you ok??)");
- //are you ok]
- //??) - 三字母词 --> ] (在早期的编译器中会将连续的??)识别为],我们的vs2019不支持三字母词)
- return 0;
- }
假设我们的编译器输出的结果就是are you ok],我们该如何做能得到正确的结果呢?这时候就需要我们的转义字符了
1.定义:转变了它原来的意思!
假如我们要在屏幕上打印一个目录: c:\code\test.c
代码如下:
- int main()
- {
- printf("c:\test\test.c");
- return 0;
- }
输出结果:
我们发现怎么跟我们预想的不一样啊?其实是\和t在一起构成了转义字符中的一种---水平制表符也就是键盘的tab键
那我们怎么做才能达到想要的效果呢?其实很简单
我们在\前面再加入一个\,防止它被解释为一个转义序列符
2.种类
\? 在书写连续多个问号时使用,防止他们被解析成三字母词
- int main()
- {
- printf("(are you ok\?\?)"); // ??) --> ] - 三字母词
- return 0;
- }
??)是三字母词,在有些编译器中输出结果会直接生成 ]
而\?\?) 能保证输出结果是 ??)
\' 用于表示字符常量'
- int main()
- {
- printf("%c\n", 'a');// %c 打印字符
- printf("%c\n", ''');//会报错系统会理解成前两个''是一组,而第三个'则是单独的
- printf("%c\n", ' \' ');//成功打印出 '
- return 0;
- }
\“ 用于表示一个字符串内部的双引号
- int main()
- {
- printf("%s\n", "abc");// %s 打印字符串
- printf("%s\n", "a");
- printf("%s\n", """);//会报错系统会理解成前两个""是一组,而第三个"则是单独的
- printf("%s\n", "\"");//成功打印出 "
- return 0;
- }
补充:print在打印数据的时候,可以指定打印的格式
- printf("%d",100);//打印整型
- printf("%c",'a');//打印字符
- printf("%s","abc");//打印字符串
\\ 用于表示一个反斜杠,防止它被解释为一个转义序列符
- int main()
- {
- printf("c:\\test\\test.c");
- return 0;
- }
这样打印的结果就是 c:\test\test.c
\a 警告字符,蜂鸣
- int main()
- {
- printf("\a\a\a");
- return 0;
- }
程序运行后会出现警报声
\b 退格符
- int main()
- {
- printf("abcdef\n");
- printf("abc\bdef\n");
- return 0;
- }
当打印完c识别出\b以后,回退一格打印后面的def,相当于键盘的Backspace
补充:2进制 8进制 10进制 16进制 不同的进制只是数据的表示形式而已
\ddd ddd表示1~3个八进制的数字。 如: \130 X
- int main()
- {
- printf("%c\n",' \130'); //8进制的130是十进制的多少呢?
- //X --ASCII码值是88,因为这里打印字符,所以根据对应的ASCII码值转换成对应的字符
- return 0;
- }
运行结果:
\xdd dd表示2个十六进制数字。 如: \x30
- int main()
- {
- printf("%c\n",' \x30');
- return 0;
- }
运行结果:
以下转移字符不做过多介绍,了解即可
\f 进纸符
\n 换行 我们已经很熟悉了
\r 回车
\t 水平制表符 例子有讲解
\v 垂直制表符
小测验:难度⭐⭐ 评论区见答案哦!!!
- //程序输出什么?
- #include <stdio.h>
- int main()
- {
- printf("%d\n", strlen("abcdef"));
- printf("%d\n", strlen("c:\test\628\test.c"));
- return 0;
- }
注释是用来解释复杂代码的
代码中有不需要的代码可以直接删除,也可以注释掉
代码中有些代码比较难懂,可以加一下注释文字
注释有两种风格:
C语言风格的注释 /* xxxxxx */ 缺陷:不能嵌套注释
C++风格的注释 //xxxxxxxx 可以注释一行也可以注释多行
在这里给大家介绍两个快捷键
这两个是我们将来常用的快捷键先按住Ctrl,再按K和C就可注释代码,同理取消也是
- #include<stdio.h>
- int main()
- {
- int input = 0;//输入的值
- printf("欢迎跟小周一起学习:");
- printf("那要好好学习吗(1/0)?>:");
- scanf("%d", &input );
- if (input == 1)//if后面()里面是判断条件,在C语言中判断相等用的是==两个等于号,一个=是赋值
- {
- printf("好offer\n");
- }
- else if (input == 0)
- {
- printf("卖红薯");
- }
- else
- {
- printf("输入错误");
- }
- return 0;
- }

用选择句来实现选择的功能,首先要把if语句的格式记住,分支语句需要在( )后加{ }在{}中书写进入这个条件以后需要做什么,上面的例子中是多重分支,如果只有两个分支,那么只需要if else即可,多重分支需要加else if,
C语言有三种语句可以用来实现循环分别是
while语句
- #include<stdio.h>
- int main()
- {
- int line = 0;
- //循环
- while (line < 30000)//格式要记住while后加(循环条件)再加{符合循环条件下执行的下一步代码}
- {
- printf("写代码:%d\n",line);
- line++;
- }
- if (line == 30000)
- {
- printf("好offer\n");
- }
- return 0;
- }

for语句(后期讲)
do ... while语句(后期讲)
补充:
在这里通过这道题给大家讲解一下多组输入的问题
- int main() {
- int iq = 0;
- //输入
- while (scanf("%d", &iq) == 1)
- {
- if (iq >= 140)
- printf("Genius\n");
- }
-
- return 0;
- }
根据题目多组输入要求,我们通过循环来实现,我们还要具体看一下scanf函数的具体使用,这里给大家推荐一个C++学习网站cplusplus.com - The C++ Resources Networkhttps://legacy.cplusplus.com/这里面有库函数的具体使用,下图就是scanf的返回值的解释
scanf函数返回的是读取到数据的个数,如果scanf函数读取失败会返回EOF EOF-end of file-文件结束标志 是define定义的EOF本质上是-1
#define EOF -1
我们输入只有一个值,那么scanf的返回值就是1,这样就可以通过
scanf("%d", &iq) == 1
这个条件来实现多组输入,那我们运行以后怎么停下来呢?可以通过按Ctrl+z来实现,在VS2019中需要按三遍就可以退出
在这里小周出一道题,大家花五六分钟的时间想一想,并不难---实现两个数相加
如果你写出来了,可以运行看一看是否实现这个功能,如果没有思路,那就看看小周写的
- int main()
- {
- int a = 0;
- int b = 0;
- //输入
- scanf("%d %d", &a, &b);
- int sum = a+b;
- //输出
- printf("%d\n", sum);
- return 0;
- }
看明白以后,跟着小周的思路往下想,我们换一种方法解决这个问题,用函数的方法来解决呢?
函数可以理解为一个模块的代码完成一个独立的功能,我们来看一下下面的代码
- int Add(int x, int y)
- {
- int z = x + y;
- return z;
- }
- //上面是定义的函数方法
- int main()
- {
- int a = 0;
- int b = 0;
- //输入
- scanf("%d %d", &a, &b);
- int sum = Add(a, b);//调用我们定义好的Add函数
- //输出
- printf("%d\n", sum);
- return 0;
- }

小周给大家画一个图,保证你一下子就明白了
是不是一下子就清晰了!!!函数的特点就是简化代码,代码复用!
要存储1-10的数字,怎么存储?C语言中给了数组的定义:一组相同类型元素的集合
int arr[10] = {1,2,3,4,5,6,7,8,9,10};//定义一个整形数组,最多放10个元素
int是数组中元素的类型,arr是数组名,10是数组中的元素个数,{ }用来存放数据,每个数据之间要用逗号隔开
C语言规定:数组的每个元素都有一个下标,下标是从0开始的。数组可以通过下标来访问的。
- int arr[10] = {0};
- //如果数组10个元素,下标的范围是0-9
那我们怎么打印出来数组的每一个元素呢?这时候就要用到我们的下标
这样就成功打印出数组里的每一个元素,通过循环依次遍历整个数组,i每次都+1.这里i++就是i=i+1
因为C语言有很多的操作符,所以就很灵活,甚至操作到二进制位,这里简答介绍为主,后面具体讲解
+ - * / %
加 减 乘 除 取余
这里特殊说明一下除和取余
>> << //后期讲
& ^ | //后期讲
= += -= *= /= &= ^= |= >>= <<=
在这里给大家简单讲解前五个,剩下的后面讲
- int main()
- {
- int a = 0;
- a = 10;//赋值
-
- a = a + 5;
- a += 5;//复合赋值
-
- a = a - 2;
- a -= 2;
-
- a = a * 3;
- a *= 3;
-
- return 0;
- }

2 + 3 中+是双目操作符,因为有两个操作数
单目操作符---只有一个操作数
- ! 逻辑反操作
- - 负值
- + 正值
- & 取地址 //后面讲
- sizeof 操作数的类型长度(以字节为单位)
- ~ 对一个数的二进制按位取反 //后面讲
- -- 前置、后置--
- ++ 前置、后置++
- * 间接访问操作符(解引用操作符) //后面讲
- (类型) 强制类型转换
! 逻辑反操作
- //C语言中如何表示真假呢?
- //0 - 假
- //非0 - 真
- //-1
-
- int main()
- {
- int a = 5;
- if (a)//a为真进入if
- {
- printf("hehe\n");
- }
- if (!a)//a为假进入if
- {
- printf("haha\n");
- }
- printf("%d\n", !a);//大家通过打印!a的值,得出C语言中的假为0
- //如果a的值为0呢?那么!a的值是5吗?
- //!a总要有一个值,大家运行程序就会发现,!a是1,这是规定,当a为假时,用1来表示真
- return 0;
- }

- 负值(用的多) + 正值(用的少)
sizeof 操作数的类型长度(以字节为单位)
- int main()
- {
- int a = 100;
- //sizeof 是一个操作符,不是函数
- //sizeof计算的是变量占有内存的大小,单位是字节
- printf("%d\n", sizeof(a));
- printf("%d\n", sizeof a);//sizeof 后边的括号省略,就说明 sizeof 不是函数
-
- printf("%d\n", sizeof(int));
- //printf("%d\n", sizeof int);//err- 这是一个错误的示范
- return 0;
- }
-- 前置、后置--
- int main()
- {
- int a = 3;
- int b = --a;//先--,后使用
- /*a = a - 1
- b = a*/
- printf("a=%d b=%d\n", a, b);//2 2
-
- int b = a--;//先使用,再--
- /*b = a
- a = a - 1*/
- printf("a=%d b=%d\n", a, b);//2 3
-
- return 0;
- }
++ 前置、后置++
- int main()
- {
- int a = 1;
-
- int b = ++a;//前置++,先++,后使用
- /*a = a + 1;
- b = a;*/
- printf("a=%d b=%d\n", a, b);//2 2
-
- int b = a++;//后置++,先使用,再++
- /*b = a;
- a = a + 1;*/
- printf("a=%d b=%d\n", a, b);//2 1
-
- return 0;
- }

小测验:难度⭐⭐
a的结果是什么?评论区见答案哦!!!
- int main()
- {
- int a = 5;
- printf("%d\n", --a);//a = ?
- printf("%d\n", a);//a = ?
- return 0;
- }
(类型) 强制类型转换
我们发现类型不一致,编译器报错说可能丢失数据,3.14会被编译器认为是double类型的数据,那我们怎么让警告消失呢?就是让3.14的类型和前面的int匹配一下-----在3.14前加(int),把3保留,小数部分直接去掉
- >
- >=
- <
- <=
- != 用于测试“不相等”
- == 用于测试“相等”
前四个操作符用法很简单和数学中的符号是一个意思,但是要注意这里的操作符和数学中的写法不一样
- int main()
- {
- int a = 4;
- int b = 5;
- if (a >= b)//(a <= b) (a == b) (a != b) 会有不同的结果
- {
- printf("hehe\n");
- }
- else
- {
- printf("haha\n");
- }
- return 0;
- }
- && 逻辑与
- || 逻辑或
也称作三目操作符(C语言中唯一一个) exp:表达式
exp1 ? exp2 : exp3
真 执行 不执行 整个表达式的结果是exp2的结果
假 不执行 执行 整个表达式的结果是exp3的结果
exp1, exp2, exp3, …expN
[]//下标引用
()//函数调用
- int Add(int x, int y)
- {
- return x + y;
- }
-
- int main()
- {
- int z = Add(3, 5);//() 函数调用操作符
- printf("hehe");//() 函数调用操作符
- return 0;
- }
. ->//结构成员,后期讲
- auto break case char const continue default do double else enum
- extern float for goto if int long register return short signed
- sizeof static struct switch typedef union unsigned void volatile while
C语言提供了丰富的关键字,这些关键字都是语言本身预先设定好的,用户自己是不能创造关键字的。在这里给大家简单分个类
auto-自动 extern -声明外部符号的 register-寄存器 static-修饰变量和函数
循环-break continue do while for while
分支-break case default 默认 else goto
数据类型-char double float int long short void
修饰类型-const signed(有符号的) unsigned(无符号的) typedef(类型重定义的)
自定义类型-enum(枚举类型) struct(结构体类型) union(联合体类型)
函数的返回-return(返回值) 计算变量/类型的大小,单位是字节-sizeof
void-函数的返回值-函数的参数(无)-修饰指针(空) volatile-很少见
- int main()
- {
- auto int num = 0;//局部的变量是进入作用域创建,出了作用域销毁了,自动创建、自动销毁的
- return 0;
- }
但是因为所有的局部变量都是如此,所以我们一般省略auto
typedef 顾名思义是类型定义,这里应该理解为类型重命名。
- //在我们以后编写代码的过程中,一定会有某些变量的类型很复杂很长,这时候我们可以利用typedef关键字对复杂的类型进行重新命名,这样在后续相同类型的创建中可以简化代码,提高效率
- typedef unsigned int u_int;//将unsigned int类型重命名为为u_int类型
- typedef unsigned long long ull;//将unsigned long long类型重命名为为ull类型
-
- int main()
- {
- unsigned int num = 0;
- u_int num2 = 0;//在这里可以直接调用,num和nun2的类型是相同的
- ull num3 = 0;
- return 0;
- }
- //typedef还可以对结构体类型重命名,结构体后期会为大家讲解,在这里简单认识即可
- typedef struct Node
- {
- int data;
- struct Node* next;
- }Node;
- //在这里把struct Node类型重命名为Node类型

在C语言中:static是用来修饰变量和函数的
修饰局部变量-称为静态局部变量
修饰全局变量-称为静态全局变量
修饰函数-称为静态函数
首先给大家3分钟的时间思考,我下面的代码运行结果
- void test()
- {
- int a = 5;
- a++;
- printf("%d ", a);
- }
-
- int main()
- {
- int i = 0;
- while (i < 10)
- {
- test();
- i++;
- }
-
- return 0;
- }

结果是不是和你想的相同呢?如果是的话,请给自己鼓个掌;如果不是,也不要灰心,听我的分析
首先main函数作为整个程序的入口,开始执行程序,符合循环条件进入循环,调用test函数,此时进入test函数,打印a的值为6,test函数结束,返回主函数继续下一行代码,此时a变量为局部变量,出作用域就销毁,主函数循环10次,调用test函数10次,每次都打印6 ,所以就是图中的结果
那再给大家5分钟时间,想想我下面程序的运行结果
- void test()
- {
- static int a = 5;//静态变量的
- a++;
- printf("%d ", a);
- }
-
- int main()
- {
- int i = 0;
- while (i < 10)
- {
- test();
- i++;
- }
-
- return 0;
- }

结果是不是与大家想的差了很多呢?那我们从结果反推看看能不能推测出static的功能
这里打印a的值是逐步递增的,这说明a其实并没有被销毁,而是一直存在的,这样才能得出上面的结果
static代替auto修饰int类型的变量a,auto表示自动创建和销毁,那static应该表示只执行一次创建过程,静态局部变量在编译时赋予初值,每次调用函数不再重新赋值,函数结束不销毁
那通过对比上述两个代码的结果,我们可以得出:
static 修饰局部变量的时候,本来一个局部变量是存放在栈区的,如果被static修饰就存储到静态区了 static 修饰局部变量改变了变量的存储类型(位置),使得这个静态变量的生命周期变长了,直到程序结束才结束,但是作用域不变
在这里给大家讲解一下什么是栈区,什么是静态区
看完这张图是不是清晰明了,对static修饰局部变量更加熟悉了呢?
之前再给大家讲全局变量有这样例子,不知道大家想起来了没有
那我们在add.c文件中加入static修饰,结果却大大不同
我们可以得出,static修饰全局变量,使得这个全局变量只能在自己所在的源文件(.c)内部可以使用其他源文件不能使用!
static 修饰全局变量,全局变量具有外部链接属性,所以在其他源文件内部依然可以使用(方法要正确) static 修饰全局变量,改变了这个全局变量的链接属性,由外边链接属性变成了内部链接属性,这个静态变量只能在自己所在的源文件内部使用,不能在其他源文件内部使用了,感觉像是作用域变小了
static 修饰函数和static修饰全局变量是一样的 函数是具有外部链接属性的,但是被static修饰,就变成了内部链接属性,使得这个函数只能在自己所在的源文件内部使用,不能在其他文件内部使用的
- int main()
- {
- //register 仅仅是建议的作用
- //建议放在寄存器中,但是不是真的放在寄存器中,取决于编译器
- register int num = 10;
-
- return 0;
- }
简单了解即可
补充:计算机存储器层次结构
编译器编译完M就不存在了,用到M的地方替换成100了
- //宏
- #define ADD(x, y) ((x)+(y))//ADD-宏的名字,(x, y)-宏的参数,((x)+(y))-宏的实现体
- //宏没有返回类型,没有参数类型
- //函数
- int Add(int x, int y)
- {
- return x + y; //{ return x+y; }函数体
- }
- int main()
- {
- int a = 10;
- int b = 20;
- int c = ADD(a, b);
- //代码编译以后,上面的代码替换为
- //int c = ((a)+(b));
- printf("%d\n", c);
- int d = Add(a, b);
- printf("%d\n", d);
- return 0;
- }

要想理解好什么是指针,首先我们要理解什么是内存,指针是用来访问内存的
我们说每一个人都有自己住的地址,一个小区一栋楼一个单元中每一层都有对应的编号,我可以通过对应的门牌号找到自己邻居好友的住处,有了房间的编号,我们可以很方便的找到对应的房间
在这里再给大家回顾一下计算机中的单位:
bit - 比特位 - 存放一个二进制位的
Byte - 字节 = 8bit
Kb - 1024 byte
Mb - 1024 kb
Gb - 1024 mb
Tb - 1024 gb
Pb - 1024 tb
- int main()
- {
- int a = 15;
- //a是int类型,所以向内存申请了4个字节的空间
- //用来存放15这个数值
- return 0;
- }
程序运行起来,要加载到内存中,也要申请内存空间使用
那我们说知道了内存以后,指针又是什么?怎么用的呢?
上面两次a的地址不同是因为每一次运行程序,编译器为a分配的内存位置都不一样
int * pa = &a;
这句代码中的pa前的*说明pa是指针变量,int则是说明pa这个指针变量中存放的a的地址,而a是int类型,即pa指向的是int类型的变量
指针 - 地址 -编号 指针变量 - 变量 - 存放地址的变量 口头语中说的指针,基本上都是指针变量
*pa = 30;
在这里就要给大家讲解一个之前没讲过的解引用操作符,我们可以在指针变量前加一个*,这样我们就可以通过直接指针变量里面存放的地,直接找到a,不用对a进行修改
大家可以这么理解:高启强要办点事,但是呢不方便自己出手,所以把事告诉老默了并跟老默说“我想吃鱼了!”,于是老默就去处理了哈哈哈哈哈!听到这里不知道你是否对指针有了一点点理解了呢?
也可以这么理解
我们发现是4个字节,那真的对吗?其实对了一半,我们此时是32位处理器
32位处理器对应的是x86,64位处理器对应的是x64
我们换成x64处理器试试呢?
我们发现出现警告,此时我们根据警告修改代码,因为此时sizeof的返回值是size_t类型,要用%zd打印
我们发现此时是8个字节,那到底是多少呢?
其实指针变量的大小根据32位处理器和64位处理器的不同而不同
指针变量是用来存放地址的
32位机器上:地址是32个二进制位,这个地址要存储的话需要4个字节,所以在32位机器上,指针变量的大小是4个字节
64位机器上:地址是64个二进制位,这个地址要存储的话需要8个字节,所以在64位机器上,指针变量的大小是8个字节
结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。
比如描述学生,学生包含: 名字+年龄+性别+学号 这几项信息。
这种是复杂对象,没有办法用单一的变量来描述所以,这里只能使用结构体来描述了
例如
- //学生
- struct Stu
- {
- //学生的相关属性
- char name[20];//名字-字符串,一个汉字是2个字符的
- int age;//年龄
- char sex[5];//“男”、女、保密
- };
- //书
- struct Book
- {
- char name[20];//书名
- char author[10];//作者名
- float price;//价格
- };
struct是结构体的关键字,然后Stu代表学生,{ }里包含了学生的基本信息,最后不要忘了";",先记住格式和基本点,后期为大家详细讲解
结构体的初始化:
- int main()
- {
- struct Stu s1 = { "张三", 20, "男" };
- struct Stu s2 = { "李四", 20, "男" };
- struct Stu s3 = { "王五", 20, "男" };
- struct Stu s4 = { "翠花", 20, "女" };
- struct Book b = { "《我与地坛》", "史铁生", 28.5f };
- //struct Stu 类型 s1是名字
- //结构体成员有多个,所以用{ },每个成员变量间用逗号隔开,字符串要用" "
- printf("%s %s %f\n", b.name, b.author, b.price);
- //.是结构体成员操作符,访问b的成员需要.
- return 0;
- }
- //学完了指针,在这里再为大家讲解另外一个操作符->
- //在这里再定义一个结构体
- struct S
- {
- char name[20];
- int age;
- float score;
- };
我们发现这三种方式打印最后的结果都是一样的,我们可以用不同的方法实现对结构体成员的访问
一种是结构体变量.成员,一种是结构体指针->成员
好啦!!!学到这你已经很厉害了!!!给自己竖一个大拇指!!!你是最棒的!!!今天小周就带大家学到这里。小周写一篇高质量详细的博客也也花了好多时间,看到这里请动动你的小手来为小周点赞推广评论一下吧!!!你们的点赞推广评论是我继续输出高质量博客的动力!!!谢谢大家!!!
欲知后事如何,且听下回分解
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。