配套视频:https://www.bilibili.com/video/BV1W34y1U7eK?spm_id_from=333.999.0.0
关于C语言C 语言是一种通用的高级语言,最初是由丹尼斯·里奇在贝尔实验室为开发 UNIX 操作系统而设计的。C 语言最开始是于 1972 年在 DEC PDP-11 计算机上被首次实现。
在 1978 年,布莱恩·柯林汉(Brian Kernighan)和丹尼斯·里奇(Dennis Ritchie)制作了 C 的第一个公开可用的描述,现在被称为 K&R 标准。
UNIX 操作系统,C编译器,和几乎所有的 UNIX 应用程序都是用 C 语言编写的。由于各种原因,C 语言现在已经成为一种广泛使用的专业语言。
优点- 易于学习。
- 结构化语言。
- 它产生高效率的程序。
- 它可以处理底层的活动。
- 它可以在多种计算机平台上编译。
- 因为C语言给编写者太大权限,你可能把握不住
C 语言最初是用于系统开发工作,特别是组成操作系统的程序。由于 C 语言所产生的代码运行速度与汇编语言编写的代码运行速度几乎一样,所以采用 C 语言作为系统开发语言。并且C语言便于理解,也是很多其他语言的母语言,通过学习C语言,我们能够快速的对编程进行一个了解,并且后续在学习其他语言的时候(语法)会更加容易,所以C语言的学习是有必要的
C语言的IDE 关于IDE:IDE就是一系列开发工具的组合套装.这就好比台式机,一个台式机的核心部件是主机,有了主机就能独立工作了,但是我们在购买台式机时,往往还要附带上显示器、键盘、鼠标、U盘、摄像头等外围设备,因为只有主机太不方便了,必须有外设才能玩的爽。
集成开发环境也是这个道理,只有编译器不方便,所以还要增加其他的辅助工具。在实际开发中,我一般也是使用集成开发环境,而不是单独地使用编译器。
通俗的称呼有时候为了称呼方便,或者初学者没有严格区分概念,也会将C语言集成开发环境称作“C语言编译器”或者“C语言编程软件”。这里大家不要认为是一种错误,就把它当做“乡间俗语”吧。
(本教程建立在Windows平台)
初学者的话使用IDE我推荐 Devcpp,这个IDE非常轻便好用
如果你想有一个好看的编辑界面,那么我建议你用VScode 或者Visual Studio
当然我还是推荐使用CLion
程序结构一个C程序包含以下部分
- 预处理指令
- 函数
- 变量
- 逻辑代码
- 注释
举个栗子:
#include
//上面是头文件,下面是函数
int main()
{
printf("Hello Mangata!");
return 0;
}
我们先来剖析一下这个C程序
第一行就是一个预处理指令,也就是我们后面讲的头文件
第二行就是一个行注释,当然我们也可以通过/* */
来达到区间块注释的效果
第三行开始到第七行就是一个标准的函数,也就是我们后面讲的主函数,要记住一个C程序一定有且只有一个main函数
第五行是一个输出语句,调用了printf
库函数
因为头文件里面有我们需要的一些基本函数,比如输入的scanf
输出的printf
,这些函数前人们已经帮我们写好了,不必我们从头开始,所以我们需要引入头文件来使用库函数,可以方便我们的程序编写
我们通过#include
的一种“指令” ,头文件的引入是预处理语句
#include
叫做文件包含命令,用来引入对应的头文件(.h
文件)。#include 也是C语言预处理命令的一种。
#include
#include "xxx.h"
这就是C语言的两种引入头文件的格式,中间的空格不是必须的(😀),xxx就是你想用的库
常用的头文件 头文件描述#include
这是一个标准输入输出的头文件#include
这是数学函数的头文件#include
这是字符串函数的头文件#include
这是时间函数的头文件#include
实用工具函数的头文件
这些大概就是平常使用较多的头文件了,关于头文件具体的哪些函数,我后面会讲一些,但是也只是常用的,所以更多的东西还需要同学们自己去网上拓展
我这里放一个这些头文件的常用函数连接:https://blog.csdn.net/acm_Mercyking/article/details/50119289感兴趣的同学可以去自己拓展一下噢
标准输入输出函数 scanf这个是标准输入函数,因为输入对格式要求很严,不过速度是非常快的,下面是scanf
的声明
int scanf(const char *format, ...)
scanf
前面那个int是返回类型,可以不用管,如果你真想知道的话,其实也很简单,就是成功输入赋值的个数
关于括号里面,自然就是传的参数咯,我们一一来看括号里面的东西,里面的结构是长下面这样的:
scanf("", );
scanf("%d",&a);
这里的例子我们用的是一个%d,这是什么意思呢?这就表示我们输入的数据的类型是一个int整形的,除了%d
我们还有%c
、%lf
、%lld
等等一系列的标准化输入的格式,具体哪种类型使用哪种符号,那就要根据使用情况看啦,也就是下面我们提到的数据类型。
标准输出其实道理和标准输入是同理的,我们先来看看这个标注输出声明
int printf(const char *format, ...)
同理函数前面有一个int的返回值,如果函数成功执行,那么就会返回输出的字符数,否则就会返回一个负数
我们再来看这个printf
的一个结构
printf("", );
printf("%d\n",a);
其实和scanf
标准输入的结构是大同小异的," "
中间放的就是格式字符形式,参量表就是你想输出的变量,可以是一个也可以是多个,也可以没有,我们直接输出字符类型的东西就不需要变量,但是请注意存在转义的情况,比如'\'
,感兴趣的同学可以去百度一下
为什么我要单独写一个关于格式化的单点呢,因为这才是格式化输入输出的一个特点或者说是小技巧
我们来看scanf
这个标准输入,在括号里面的双引号里面的是我们格式化输入的东西,我举个栗子:
如果有一个题目是这样的,要求你输入一个 Mangata+(数字),然后把数字输出出来,如果学过字符串处理的同学,应该就会觉得那直接一个正则,或者把Mangata去掉,然后输出
这样都可以,甚至来说第二种更加好,但是如果这个数字不大,并且要求你对这个数字做一些计算上的操作呢?这里我们就能用到scanf
的格式化输入了:
#include
int main() {
int a;
scanf("Mangata%d",&a);
printf("%d\n",a);
return 0;
}
再比如说如果我们需要输出一个时间例如这样08:01,有这种前置零,通过字符串的输出要麻烦得多,我们可以直接通过格式化输出:
#include
int main() {
printf("%02d:%02d",8,1);
return 0;
}
由于本书只是速通教程,所以我不在做过多的列举,更多的东西还是要靠同学们自己学习啦
数据类型 整数类型 类型存储大小值的范围char
(默认就是signed
)1字节-128~127或者0 ~ 255unsigned char
1 字节0 ~ 255signed char
1 字节-128~127int
2 或 4 字节-32768 到 32767 或 -2147483648 到 2147483647unsigned int
2 或 4 字节0 ~ 65535 或 0 ~ 4294967295short
2 字节-32768 ~ 32767unsigned short
2 字节0 ~ 65535long
4 字节-2147483648 ~ 2147483647unsigned long
4 字节0 ~ 4294967295long long
8字节-9223372036854775808~9223372036854775807
浮点类型
类型存储大小值范围精度float
4 字节1.2E-38 ~ 3.4E+386 位有效位double
8 字节2.3E-308 ~ 1.7E+30815 位有效位long double
16 字节3.4E-4932 ~ 1.1E+493219 位有效位
我们可以通过一个关键字sizeof
来获得一个类型或者说后面的变量等等的大小
举个栗子:
#include
int main()
{
printf("%d\n",sizeof(char));
printf("%d\n",sizeof(int));
printf("%d\n",sizeof(long));
printf("%d\n",sizeof(double));
return 0;
}
/*
输出结果
1
4
4
8
*/
这里我们使用了printf
库函数和sizeof
关键字 ,前者是打印函数,后者是计算对象内存大小的关键字
我这里列举一下常用的几个格式化符号:
类型输入格式化输出格式化int
%d
%d
char
%c
%c
float
%f
%f
double
%lf
%lf
或者%f
long long
%lld
%lld
字符串%s
%s
void 类型
- void类型可以拿来修饰函数,函数也就不需要一个返回值,我们之后在讲
- void类型可以拿来修饰指针,这种指针我们可以通过强制转换来实现转换到任意数据类型
我这里放一张C语言包含的数据类型的图,便于大家理解记忆:
关于其他没讲的类型在下面我会一一讲解的,不用担心啦!
变量 命名规则- 变量名的开头必须是字母或下划线,不能是数字。实际编程中最常用的是以字母开头,而以下划线开头的变量名是系统专用的。
- 变量名中的字母是区分大小写的。比如 a 和 A 是不同的变量名,num 和 Num 也是不同的变量名。
- 变量名绝对不可以是C语言关键字,这一点一定要记住!(关于关键字可以看下面的关键字表格,记住常用的就行了)
- 变量名中不能有空格。这个可以这样理解:因为上面我们说过,变量名是字母、数字、下划线的组合,没有空格这一项。
关于编程命名规范您可以参考这个博客:https://www.cnblogs.com/wfwenchao/p/5209197.html 当然你也可以用拼音
举个例子:
int temp;//定义了一个int数据类型的变量,名叫temp
char str;//定义了一个char数据类型的数据变量,名叫str
double num;//定义了一个double数据类型的数据变量,名叫num
变量定义就是告诉编译器在何处创建变量的存储,以及如何创建变量的存储。变量定义指定一个数据类型,并包含了该类型的一个或多个变量的列表
比如你要定义四个变量,这四个变量都是int类型的,你就可以将他们写在一起,他们之间用,隔开末尾以;结束
int a,b,c,d;
int e = 10;
上述的例子都是定义,那么什么是声明呢?,我们来看两个例子
-
使用关键字修饰
extern int a;//表示的其他文件以及定义过a这个变量,我们这里直接拿来使用
-
函数声明
void f(int a);//没有返回类型的函数声明
声明和定义最重要的区别就是:定义创建了对象并为此对象分配了内存,而声明并未分配内存
强制转换这个东西不难,讲起来也很简单,但是还算比较重要所以单独讲一下:
其实在程序中字节长度较高的变量对字节长度较低的变量有一定的兼容性的,但是低的对高的可不是了,因为很可能造成数据的溢出,或者是不同数据类型之间float和int,我们得到的是一个float值,但是我们想保存一个int值,那么这个时候就需要用到强制转换,我举个栗子:
#include
int main ()
{
float a = 1.234;
int b = (int)a;
printf("a = %f\tb = %d\n",a,b);
return 0;
}
这个栗子很简单,我们下面到内存控制的时候使用malloc
也是需要强制转换的。
-
**左值(
lvalue
):**指向内存位置的表达式被称为左值(lvalue
)表达式。左值可以出现在赋值号的左边或右边。 -
**右值(
rvalue
):**术语右值(rvalue
)指的是存储在内存中某些地址的数值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不能出现在赋值号的左边。 变量是左值,因此可以出现在赋值号的左边。数值型的字面值是右值,因此不能被赋值,不能出现在赋值号的左边。
举个栗子:
int a = 20;
在这个语句中a就是一个指向内存的变量也就是左值,20就是存储在内存某个地址的数值,有了这个概念就能理解下面的这个语句了
int a = 0;
a = a + 1;
printf("%d\n",a);
这里我们声明了一个int
类型的变量a,然后在声明的时候给它定义了初值为0,然后第二个语句我们让a = a + 1
,注意此时左边的a是一个变量,也就是上面我们说的左值,右边是a的值加上1,也就是右边的整体构成了一个右值,其实对于左值右值不必纠结太多,这个语句实现的效果就是a自增1,也就是说如果我们运行上面的代码的话会给我们打印一个1,这个1就是通过运算后a的值
注意此数值常量非彼数值,我此处所说的常量是单纯的一个值,没有名字那种,比如 3 他是一个整形常量 0.3 是一个浮点常量再比如说 'c'
它是一个字符常量 "ccc"
它是一个字符串常量,这种就是数值常量了,一般只是用来初始化,而且这种数值常量不易维护,比如说我们在一个程序的很多地方都用了同一个常量那么如果你想修改这个常量的值,稍微笨点的同学可能会一个一个的替换,有的同学可能想到了直接文件全局替换,但是这样做是有风险的,比如我的常量为1,我想把它替换为2,但是我可能有一些其他的常量是1开头的,比如12,那么就会造成数据紊乱,甚至有些变量里面也包含了1那么可能会导致编译出错,再退一步讲,编译没问题,程序的运行结果也不会和预期一样
说的浅显易懂点,define就是一个文本替换,格式如下
#define xxx yyy //达到的效果就是下面的程序所有用到的xxx都会被替换为yyy
#define x 10//这里就表示x是一个常量,它表示的value是10
- 当然你也可以通过#define 来实现宏函数eg:
#define max(a,b) (a>b?a:b)
#define
是一个预处理指令,所以在书写代码的时候请将#define
放在程序的顶部#define
后面没有分号 !- 请尽量少使用
#define
,因为#define
相当于一种文本替换,在代码行数较少发生的问题较少,但是在代码量较大的时候这种常量就会存在一种潜在的危险->冲突(如果报错还好,没有报错那就难受了,大概率程序的运行结果和预期不同)
const是constant的缩写,是一个修饰词用于修饰一些变量,通过const修饰符的变量就变成了一个不可变的变量
eg:
const int a = 10;//这就是定义了一个常量,名叫a,值为10
- 通过
const
修饰后不能更改值 - 我们可以通过指针修改
const
定义的常量
大体上分为三类
- 一、
const
修饰指针指向的内容,则内容不可变,但是能通过一个同数据类型的指针来改变值
const int *a = 10;// 这样的内容不可变
- 二、
const
修饰指针,那么指针的值不可变
int a = 10;
int* const b = &a;
此时的const
修饰的是指针,那么指针指向的地址不可变,也就是此时的b指向的地址不能边变,但是*b可变,请同学们要想明白
- 三、
const
修饰指针并且修饰的指针指向的内容,那么指针指向的地址和值都不可变
int a = 10;
const int * const b = &a;
此时的b指向的地址不能更改,地址上的值*b也不能更改
存储类 autoauto是一种默认的存储类,作用范围是局部,一般不用管,生命周期和作用域都是局部的
static这是一个静态的存储类,它有点特殊的是他的生命周期是整个程序从开始到结束,但是它的作用域只是局部
举个栗子:
#include
void f() {
static int a = 0;
a++;
printf("%d\n",a);
}
int main()
{
for(int i = 0;i a= 3-
对两个数进行相减a = 2 - 1 => a = 1*
对两个数进行相乘a = 2 * 2 => a = 4/
对两个数进行相除a = 10 / 2 => a = 5%
a对b取模a = 10 % 3 = > a = 1++
变量自增1a = 0; ++a => a = 1--
变量自减1a = 0 ; --a => a = -1
关系运算
运算符描述实例==
检查两个操作数的值是否相等,如果相等则条件为真。(A == B) 为假。!=
检查两个操作数的值是否相等,如果不相等则条件为真。(A != B) 为真。>
检查左操作数的值是否大于右操作数的值,如果是则条件为真。(A > B) 为假。=
检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。(A >= B) 为假。
从左到右关系< >=
从左到右相等== !=
从左到右位与 AND&
从左到右位异或 XOR^
从左到右位或 OR|
从左到右逻辑与 AND&&
从左到右逻辑或 OR||
从左到右条件?:
从右到左赋值= += -= *= /= %=>>=
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?