1.C语言的介绍
C语言是一门通用的计算机变成语言,广泛应用于底层开发。C语言不仅提供低级处理的功能,还有良好的跨平台性。C语言可在许多平台上编译,还包含一些嵌入式处理器(单片机)以及超级电脑等作业平台。二十世纪八十年代,为避免C语言语法产生差异,美国国家标准局为C语言制定了标准语法,简称ANSI C。由国际标准化组织(ISO)和国际电工委员会(IEC)发布的C11标准是C语言最新的标准。
C语言是一门面向过程的计算机编程语言。C++,Java是面向对象的编程语言。
C语言编译器包括Clan、GCC、WIN-TC、SUBLIME、MSVC、Turbo C等。
2.第一个C语言程序
#include<stdio.h>
int main()
{
printf("Hello World!\n");
return 0;
}
这是最简单的一段C语言代码,起作用是在屏幕上打印 Hello World! 这段字符。
解释: int main(){ example return 0} main()是主函数,不管main函数在哪个位置,main函数是整个程序的入口,一个工程有且只能有一个。main前面的的int是数据类型,再次是说明main函数的返回类型,对应return 0;当然这个也可以写成其他的整数,让我们判断程序是否正常结束。printf();这个函数的效果是在屏幕前打印,这个函数的声明和定义包含在头文件 stdio.h中。
3.C语言的数据类型
3.1数据类型
char 字符类型(也是整形)
short 短整形
int 整数类型
long 长整形
long long 超长整形
float 单精度浮点数
double 双精度浮点数
#include<stdio.h>
int main()
{
printf("size of char:%d\n",sizeof(char));
printf("size of short:%d\n",sizeof(short));
printf("size of int:%d\n",sizeof(int));
printf("size of long:%d\n",sizeof(long));
printf("size of long long:%d\n",sizeof(long long));
printf("size of float:%d\n",sizeof(float));
printf("size of double:%d\n",sizeof(double));
return 0;
}
以上代码显示的是每个数据型类型的大小,单位是字节。
注:sizeof()计算的括号内类型的大小,单位是字节。
各类型的范围
各类型的大小的定义和范围可以再 limits.h头文件中查看
也可以使用以下代码来查看各类型的最大值最小值
#include<stdio.h>
#include<limits.h>
int main()
{
printf("CHAR_MAX:%d\n",CHAR_MAX);
printf("CHAR_MIN:%d\n",CHAR_MIN);
printf("SHORT_MAX:%d\n",SHRT_MAX);
printf("SHORT_MIN:%d\n",SHRT_MIN);
printf("UNSIGNED SHORT_MAX_MAX:%u\n",USHRT_MAX);
printf("INT_MAX:%d\n",INT_MAX);
printf("INT_MIN:%d\n",INT_MIN);
printf("LONG_MAX:%ld\n",LONG_MAX);
printf("LONG_MIN:%ld\n",LONG_MIN);
return 0;
}
以上种种不在尝试
类型的使用
char ch='s';
int num1=10,num2=9,num;
double num3=90.0;
其中ch num1 num2等是变量名,右边是给变量赋值。
3.2变量
变量的分类
- 全局变量
- 局部变量
全局变量的作用范围是整个工程内,在其他文件也能访问。
局部变量的作用范围是该变量所在的局部范围呢,且出了作用域生命周期就结束。
#include<stdio.h>
int global=2023;//全局变量
int main()
{
int local=2022;//局部变量
{
int local_m=2018;//局部变量 只能在这个作用域(括号内)使用
}
printf("glocal=%d local=%d\n",global,local);
printf("local_m=%d",local_m);//这行代码会出错,因为已经出了作用域
return 0;
}
变量的使用
#include<stdio.h>
int main()
{
int a=0,b=0;
printf("请输入两个数:");
scanf("%d %d",&a,&b);
printf("两数之和为%d\n",a+b);
return 0;
}
以上代码是使用两个变量并对其赋值,在屏幕中打印输入的数之和。
解释:scanf()是输入函数,&a,&b,是去除变量a和变量b的地址,c语言操作的是内存,变量a和变量b只是形式实际操作的是a和b所在的地址。%d是占位符,是整数类型的占位符。其他的占位符还包括
%c读入一个字符类型
%d 读入一个十进制整数
%i读入十进制,八进制,十六进制整数
%o读入八进制整数
%x读入十六进制整数
%s读入字符串,遇空格、制表符或换行符结束
%p读入一个指针
%u读入一个无符号十进制数
%f %F %e %E %g %G用来输入实数,可以用小数形式或指数形式输入
占位符与数据类型的对应关系
%c | char |
%u | unsigned int |
%d | int |
%f | float |
%lf | double |
%ld | long |
%hd | short |
%lu | unsigned long |
%hu | unsigned short |
3.3常量
C语言常量可分为以下几种
- 字面常量
- const修饰的常变量
- #define定义的标识符常量
- 枚举常量
#include<stdio.h>
#define MAX 100 //#define的标识符常量
enum Sex{
MALE,
FEMALE
};
//括号中MALE FEMALE枚举常量
int main()
{
2.55;//常量
"hello world";、/常量
const float pai=3.14;
return 0;
}
4.字符串+转义字符+注释
4.1字符串
"hello world"
这种由双引号括起来的一串字符称为字符串。
注:字符串结束的标志是'\0',在计算字符串常量的长度是不计算'\0'的长度,但是用sizeof会计算'\0'的大小,'\0'的ASCII值为0
#include<stdio.h>
#include<string.h>
int main()
{
printf("%d\n",strlen("hello world"));
printf("%d\n",sizeof("hello world"));
return 0;
}
代码运行结果为:
11
12
4.2转义字符
#include<stdio.h>
#include<string.h>
int main()
{
printf(""hello world"");//这行代码会有错误,本意是想打印"hello world",实际上编译会出错
return 0;
}
C语言中""等符号会自动对齐,这就导致我们无法打印想看到的内容,这就引出以下要说的转移字符。
转移字符 | 释义 |
\? |
在书写连续多个问号时使用,防止他们被解析成三字母词
|
\'
|
用于表示字符常量
'
|
\“
|
用于表示一个字符串内部的双引号
|
\\
|
用于表示一个反斜杠,防止它被解释为一个转义序列符。
|
\a |
警告字符,蜂鸣
|
\b
|
退格符
|
\f
|
进纸符
|
\n | 换行符 |
\r | 回车 |
\t |
水平制表符 相当于tab
|
\v |
垂直制表符
|
\ddd
|
ddd
表示
1~3
个八进制的数字。如\35 \132 \1
|
\xdd
|
dd
表示
2
个十六进制数字。如\x30 \AE
|
4.3注释
注释的代码不会运行,注释可以提高代码的可读性
C语言注释方式有两种
//单行注释
/* */多行注释
#include<stdio.h>
int main()
{
//我不会被运行
/*
我也不会被运行
*/
printf("hello world");
return 0;
}
代码正常运行 输出结果
hello world
5.选择结构
顺序选择结构表达式
if(condition)
{
expression;
}
....
....
#include<stdio.h>
int main()
{
printf("是否执行条件语句?1-执行 其他数字-不执行\n请输入>>");
int cot;
scanf("%d",&cot);
if(cot==1)
{
printf("已执行循环语句\n");
}
return 0;
}
分支选择结构表达形式是
if(condtion){
expression1;
}else
{
expression2;
}
如果条件condition为真(非零)则执行表达式expression1,否则执行表达式expression2
#include<stdio.h>
int main()
{
int choice;
printf("是否好好学习? yes(1)\ninput>>");
scanf("%d",&choice);
if(choice==1)
{
printf("好好学习找到工作\n");
}
else{
printf("注意进场时机\n");
}
}
多分支选择
若满足条件一则 执行语句一若满足条件二则执行语句3,其他条件则执行语句2
#include<stdio.h>
int main()
{
int choice;
printf("0.结束游戏\n1.开始游戏\n其他:请重新输入!\n请选择>>");
scanf("%d",&choice);
if(choice==0)
printf("结束游戏");
else if(choice==1)
printf("开始游戏");
else
printf("请重新输入");
return 0;
}
6.循环语句
循环语句可分为3种
while循环语句
do...while循环
while循环用法
while(条件表达式)
{
expression;
}
当条件不满足时跳出循环
//while循环实例
#include<stdio.h>
int main()
{
int i=0;
while(i<=100)
{
printf("第%d天好好敲代码\n",i);
i=i+1;
}
return 0;
}
for循环用法
for(初始化表达式(opt);条件表达式(opt);循环表达式(opt))
{
expression;
}
for(init-expression;cond-expression;loop-expression);
//这三个表达式都是可选的
for(;;);
//直接编译以上代码是不会报错的
1.若有初始化表达式(init-expression)已被赋值.。则他声明了循环的初始化,对于初始化表达式是没有限制的,而且只会执行一次
2.若有条件表达式(cond-expression)已被赋值。则表达式必须包含算数或者指针表达式。若条件表达式被省略,则条件一直为真,循环将一直执行下去直到遇到break或者return结束。
#include<stdio.h>
int main()
{
for(int i=0;;i++)
{
if(i==1000)
{
break;
}
printf("%d\n",i);
}
return 0;
}
//该代码会按顺序打印1到999并退出循环
while循环和for循环的条件表达式(cond-expression)会比循环内的语句多执行一次。
dowhile循环用法
do
{
expression;
}while(cond-expression);
该种循环会先执行一次,然后判断条件
//实例
#include<stdio.h>
int main()
{
int i=0;
do
{
i++;
printf("第%d次执行循环\n",i);
}while(i<=100);
return0;
}
7.函数
函数是一种子程序,利用函数名称,可以接收回传值。
函数是完成某一功能的子程序,相较于其他代码要有独立性,要满足高内聚,低耦合。
函数的特点就是简化代码,代码复用。
其形式一般为
ret_type func_name(para1,para2....)
{
statements;
return ret_type data;
}
int add(int a,int b)
{
return a+b;
}
//这便是一个简单的函数,用于计算两个整数相加的值用法如下
int a=5;c=10;
int b=add(a,c);
//b的值就为15
除了以上自定义的函数,C语言还有库函数,是已经封装好可以直接用的。就比如之前的经常使用的scanf 和printf,都包含在头文件 stdio.h中。使用库函数时,一定要引用对应的头文件。
对于自定义函数,在使用前要先声明。
#include<stdio.h>
int main()
{
int a=5,c=10;
int b=add(a,c);
return 0;
}
int add(int a,int b)
{
return a+b;
}
//这段代码会报错,主函数在调用add函数时,并没有找到该函数
//正确的用法如下
#include<stdio.h>
int add(int a,int b)
{
return a+b;
}
int main()
{
int a=5,c=10;
int b=add(a,c);
return 0;
}
//或者如下
#include<stdio.h>
int add(int x,int y);//这里是函数声明
int main()
{
int a=5,c=10;
int b=add(a,c);
return 0;
}
int add(int a,int b)//这里是函数的定义也就是具体实现
{
return a+b;
}
//在调用函数时,必须要在使用前声明该函数才能正常使用
函数参数
形式参数就比如以上代码中int add(int x,int y);这里的x,y就是形式参数,形式参数在函数被调用时才实例化。在函数调用节术后自动销毁。
实际参数就比如如上代码int b=add(a,c);中的a,c就是实际参数,在函数调用时,必须传入具体的值,这便是实际参数。
函数的调用
传值调用和传址调用
先看一下例子
#include<stdio.h>
void swap(int a,int b)//交换传入的两个整数
{
int temp=a;
a=b;
b=temp;
}
int main()
{
int a,b;
scanf("%d %d",&a,&b);
printf("交换前:a=%d b=%d\n",a,b);
swap(a,b);
printf("交换后:a=%d b=%d\n",a,b);
}
结果是
为是什么会出现以上结果呢。
原因是函数在调用时,内存会为函数开辟一个新的内存空间,函数执行时里面的参数是对传入参数的一份临时拷贝,在函数调用结束是就销毁了,此a,b非彼a,b,内存中没有变量名,只有地址。以上传参方式就是传值调用。
接下看看传址调用。
#include<stdio.h>
void swap(int* a,int* b)//交换传入的两个整数
{
int temp=*a;
*a=*b;
*b=temp;
}
int main()
{
int a,b;
scanf("%d %d",&a,&b);
printf("交换前:a=%d b=%d\n",a,b);
swap(&a,&b);
printf("交换后:a=%d b=%d\n",a,b);
}
这里&是取地址符,*在这里是解引用操作(这里是个单目运算符),就是访问该地址上的值。这里我们传入的参数就是main函数中a和b的地址,对这两个地址进行互换值的操作,就算函数调用结束,main函数中a,b的实际值也依然发生改变。
函数递归
什么是递归
- 存在限制条件,当满足限制条件时,便结束递归
- 每次递归都慢慢接近限制条件
先来一个简单实例,递归法求n!
#include<stdio.h>
int fact(int n)
{
if(n==0||n==1) return 1;
return n*fact(n-1);
}
int main()
{
int n=5;
int ans=fact(5);
printf("%d",ans);
return 0;
}
//输出结果为120
//调用的过程为fact(5)5*fact(4)
//fact(4)=4*f(3)...
//层层调用,每一次调用接近n==1这个条件
函数调用是通过压栈来保存信息的。以上就是fact(5)的调用过程。
8.数组
数组就是一类数据的集合
其形式为
type array_name[size];
//数组的使用
int num1[10];//声明了一个整形数组,大小为10个整形
int num2[10]={0};//声明了一个数组并赋初值
char str[20]="hello world";
//对于数组的访问
for(int i=0;i<10;i++)
{
printf("%d",arr[i]);
}
//数组的下标是从0开始的 比如num1数组,其下标范围是0~9
9.操作符
算数运算符
+ - * / %
其中%是取余运算,要求%的两个操作数为都为整数,算数运算符都是双目运算符
位移运算符
>> <<
右移 左移
左移右移都是针对二进制进行的,数据在二进制中是以补码的形式进行存储的。这个以后再聊。同样,左移右移也是双目运算符。对于移位运算符,不要移动负数位,这个是标准未定义的。
位运算符
| 按位或 & 按位与 ^异或
| & ^都是双目运算符,操作的对象也是二进制数。
| 只要有1就是1
eg a=10011001
b=10100100
a|b=10111101
& 两个都是1就是1
eg a=10011001
b=10100100
a&b=10000000
^同0异1
eg a=10011001
b=10100100
a^b=00111101
^一个重要性质 a^a=0;
赋值操作符
= += -= *= /= >>= <<= ^= |=
a+=b 等同于 a=a+b其余同理
单目操作符
! | 逻辑反操作 |
- | 负号 |
+ | 正号 |
& | 取地址(引用) |
sizeof | 操作数的类型长度(单位字节) |
~ | 按位取反 |
-- | 自减 |
++ | 自增 |
* | 简介访问(解引用) |
(类型) | 强制类型转换 |
关系操作符
>
>=
<
<=
== 测试相等
!= 测试不等
关系操作符是双目运算符
逻辑运算
|| 逻辑或
&& 逻辑与
逻辑运算符为双目运算符
条件运算符
exp1?exp2:exp3
条件操作符为三目运算符exp1的结果要为数据类型或者指针类型。若表达式结果为真,则执行表达式exp2,否则执行表达式exp3。
//条件操作符的一个简单实例 求两个整数的最大值
#include<stdio.h>
int max(int a,int b)
{
return a>b?a:b;
}
int main()
{
int a,b;
printf("请输入两个数>>");
scanf("%d %d",&a,&b);
int ans=max(a,b);
printf("max=%d\n",ans);
return 0;
}
逗号表达式
exp1,exp2,exp3,...expN
式子从左到右执行,逗号表达式的结果为最后一个式子的结果
//条件操作符的一个简单实例 求两个整数的最大值
#include<stdio.h>
a
int main()
{
int a,b;
printf("请输入两个数>>");
scanf("%d %d",&a,&b);
int c=(a--,b+=8,a+b+8);
printf("c=%d",c);
return 0;
}
下标引用、函数调用和结构成员
[] () . ->
10.常见关键字
关键字不能作为变量名
auto break case char const continue 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