c语言是什么
C语言一经出现就以其功能丰富、表达能力强、灵活方便、应用面广等特点迅速在全世界普及和推广。C语言不但执行效率高而且可移植性好,可以用来开发应用软件、驱动、操作系统等。C语言也是其它众多高级语言的鼻祖语言,所以说学习C语言是进入编程世界的必修课。
- C语⾔是一门编译型计算机语⾔,C语言源代码都是文本文件,文本文件本身无法执行,必须通过编译器翻译和链接器的链接,生成⼆进制的可执执行件,可执行文件才能执行。
- C语⾔代码是放在 .c 为后缀的文件中的,要得到最终运行的可执行程序,中间要经过编译和链接2个过程。
1.编译器:计算机语言转换成机器能够执行的机器指令。
2.集成开发环境(IDE)用于提供程序开发环境的应⽤程序,⼀般包括代码编辑器、 编译器 、 调试器和图形用户页面等页面。集成了代码编写功能、分析功能、编译功能、调试功能等⼀体化的开发软件服务套。
1.输出一个hello word
1.#include<stdio.h> 这是一个头文件,其中就包含当前的printf函数()。
2.printf(“hello word”) 双引号引起来的一些字符叫字符串
3.分号:代表当前语句结束
4.return 0;当执行的过程中,遇到return代表当前的函数结束;return 0;代表语句正常结束。return -1;代表语句异常结束。
5.方法的返回值类型 int
6. .exe代表可执行程序(当我们代码写好后就变成了这个.exe)
7. 源代码(.c) 经过预编译,编译,汇编,链接变成 可执行程序(.exe)
8.main函数是程序的入口函数,只能有一个。
一.数据类型
10. char(%c) short(%d) int(%d) long(%ld) long long(%lld)
float(%f) double(%lf) 字符串的类型是%s;
1.1 新加的布尔类型
- C语言布尔类型是_Bool或者bool,使用需要包含头文件stdbool.h
- 布尔类型变量的取值是:true或者false
_Bool flag = true;
if (flag)
printf("i like C\n");
1.2 sizeof 求字节大小的(不同位数下的字节不同)
1.3 主函数main()
1.int main() 这个是一个程序的入口,main函数有且只有一个,一个c语言的程序是从本程序的main函数开执行的。
2.main函数的位置可以在任意位置,但是如果在主函数之中调用了哪些函数,必须在main函数前对其所调用函数进行生命或包含其被调用函数的头文件。
1.4 ASCLL码表
二.变量 常量
1.变量
1.局部变量与全局变量名字不要相同,容易产生bug。
2.当局部和全局变量名字相同时,局部变量优先,就是{}main()函数内优先。
3.局部变量的作用域是变量所在的局部范围。
4.全局变量的作用域是整个过程。
5.字符串的结束标志是"/0" --转义字符。
2.1 定义变量的方法
int age = 150;
float weight = 45.5f;
char ch = 'w';
2.2 变量的分类
- 局部变量
- 全局变量
- 局部变量是放在内存的栈区的,全局变量是放在内存的静态区
2.3 变量的使用
#include <stdio.h>
int main()
{
int num1 = 0;
int num2 = 0;
int sum = 0;
printf("输入两个操作数:>");
scanf("%d %d", &num1, &num2);
sum = num1 + num2;
printf("sum = %d\n", sum);
return 0;
}
//这里介绍输入,输出语句
//scanf 输入
//printf 输出
2.4 变量的作用域和生命周期
- 作用域:作用域 (scope) 是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/或者可用的而限定这个名字的可用性的代码范围就是这个名字的作用域。
1. 局部变量的作用域是变量所在的局部范围。2. 全局变量的作用域是整个工程。3.局部变量是放在内存的栈区的,全局变量是放在内存的静态区
- 生命周期:变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段
1. 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。2. 全局变量的生命周期是:整个程序的生命周期。
2.5 常量
字面常量
const 修饰的常变量
#define 定义的标识符常量
枚举常量
#include <stdio.h>
enum Sex
{
MALE,
FEMALE,
SECRET
};
//括号中的MALE,FEMALE,SECRET是枚举常量
int main()
{
//字面常量演示
3.14;//字面常量
1000;//字面常量
//const 修饰的常变量
const float pai = 3.14f; //这里的pai是const修饰的常变量
pai = 5.14;//是不能直接修改的!
//#define的标识符常量 演示
#define MAX 100
printf("max = %d\n", MAX);
//枚举常量演示
printf("%d\n", MALE);
printf("%d\n", FEMALE);
printf("%d\n", SECRET);
//注:枚举常量的默认是从0开始,依次向下递增1的
return 0;
}
三.标识符
标识符只能由字母,数字,下划线组成,且第一个字符必须为字母或者下划线。
四. 字符串+转义字符+注释
4.1 字符串
- 注:字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串内容。
转义字符
|
释义
|
\?
|
在书写连续多个问号时使用,防止他们被解析成三字母词
|
\'
|
用于表示字符常量
'
|
\“
|
用于表示一个字符串内部的双引号
|
\\
| 用于表示一个反斜杠,防止它被解释为一个转义序列符。 |
\a
| 警告字符,蜂鸣 |
\b
| 退格符 |
\f
| 进纸符 |
\n
| 换行 |
\r
| 回车 |
\t
| 水平制表符,通常下一个是8的倍数 |
\v
| 垂直制表符 |
\ddd
| ddd表示1~3个八进制的数字。 如: \130 X |
\xdd
| dd表示2个十六进制数字。 如: \x30 0 |
4.2 转义字符/0的作用
- C语⾔字符串中⼀个特殊的知识,就是在字符串的末尾隐藏放着⼀个 \0 字符,这个 \0 字符是字符串的结束标志。
- 字符串的打印格式可以使⽤ %s 来指定
4.3 算术操作符:+、-、*、/、%
4.4 各运算符之间的优先级
第1优先级:各种括号,如()、[]等、成员运算符.;
第2优先级:所有单目运算符,如++、-、!、~等;
第3优先级:乘法运算符*、除法运算符1、求余运算符%;
第4优先级:加法运算符+、减法运算符-;第5优先级:移位运算符<<、>>;
第6优先级:大于运算符。>、大于等于运算符>=、小于运算符<、小于等于运算符<=;
4.5 注释
- C语言风格的注释 /*xxxxxx*/ 缺陷:不能嵌套注释
- C++风格的注释 //xxxxxxxx 可以注释一行也可以注释多行
五. 语句与语句分类
5.1 if条件判断语句
以上就是一个简单的选择语句。
5.2 复合语句
5.3 控制语句
1. 条件判断语句也叫分⽀语句:if语句、switch语句;2. 循环执行语句:do while语句、while语句、for语句;3. 转向语句:break语句、goto语句、continue语句、return语句。后期会给⼤家⼀⼀介绍控制语句。
六.printf函数
- 例:printf("%5d\n",123) 结果为: 123 %5d 表示这个占位符的宽度至少为5位。如果不满5位,对应的值的前面会添加空格。
- 例:printf("%5d\n",123456789) 结果为:123456789
5.%6.2f 表⽰输出字符串最小宽度为6,⼩数位数为2。所以,输出字符串的头部有两个 空格
float类型,默认小数点后有6位数字
七.scanf函数
3.在scanf中如果参数是数组,因为数组本来就是地址,所以不需要取地址 例:printf("%s",arr);
4.scanf() 处理数值占位符时,会⾃动过滤空白字符,包括空格、制表符、换行符等
八.条件操作符
- exp1 ? exp2 : exp3
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int m = a>b ? a : b; //此处就是三目运算符的操作
printf("%d\n", m);
return 0;
}
九.逻辑操作符:&& , || , !
十.swith语句
switch (expression) {
case value1: statement
case value2: statement
default: statement
}
- switch 后的 expression 必须是整型表达式
- case 后的值,必须是整形常量表达式
10.1 if语句和switch语句的对比
输⼊任意⼀个整数值,计算除3之后的余数
用if语句来写
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
if(n%3 == 0)
printf("整除,余数为0\n");
else if(n%3 == 1)
printf("余数是1\n");
else
printf("余数是2\n");
return 0;
}
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
switch(n%3)
{
case 0:
printf("整除,余数为0\n");
break;
case 1:
printf("余数是1\n");
break;
case 2:
printf("余数是2\n");
break;
}
return 0;
}
- case 和后边的数字之间必须有空格
- 每⼀个 case 语句中的代码执⾏完成后,需要加上 break ,才能跳出这个switch语句。
10.2 switch语句中的break
10.3 switch语句中的default
在使⽤ switch 语句的时候,我们经常可能遇到⼀种情况,比如 switch 后的表达式中的值⽆法匹 配代码中的 case 语句的时候,这时候要不就不做处理,要不就得在 switch 语句中加入default 子句
switch (expression) {
case value1: statement
case value2: statement
default: statement
}
十一.数组
11.1 一维数组
1. 数组的概念
数组是⼀组相同类型元素的集合;
- 数组中存放的是1个或者多个数据,但是数组元素个数不能为0。
- 数组中存放的多个数据,类型是相同的。
11.1⼀维数组的创建和初始化
type arr_name[常量值];
- type 指定的是数组中存放数据的类型,可以是: char、short、int、float 等,也可以自定义的类型
- arr_name 指的是数组名的名字,这个名字根据实际情况,起的有意义就行。
- [] 中的常量值是用来指定数组的大小的,这个数组的大小是根据实际的需求指定就⾏。
int math[20];
11.2初始化
//完全初始化
int arr[5] = {1,2,3,4,5};
//不完全初始化
int arr2[6] = {1};//第⼀个元素初始化为1,剩余的元素默认初始化为0
//错误的初始化 - 初始化项太多
int arr3[3] = {1, 2, 3, 4};
11.3. 一维数组的下标
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
11.4 一维数组的打印
#include <stdio.h>
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int i = 0;
for(i=0; i<10; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
11.2 二维数组
type arr_name[常量值1][常量值2];
例如:
int arr[3][5];
double data[2][8];
int data[3][5] = { {1,2},{3,4},{5,6} };
3.不完全初始化
int arr1[3][5] = {1,2};int arr2[3][5] = {0};
4.打印二维数组(完全初始化)里面的元素
5.初始化时省略行,但是不能省略列
int arr5[][5] = {1,2,3};int arr6[][5] = {1,2,3,4,5,6,7};int arr7[][5] = {{1,2}, {3,4}, {5,6}};
6.二维数组的下标
int arr[3][5] = {1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7};
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int a[3][3] = {1,2,3,4,5,6,7,8,9};
int i = 1;
int m = 1;
for (i = 0; i <= 2; i++)
m = m * a[i][i];
printf("m=%d\n", m);
return 0;
}
还有一些练习题可以去我的博客c语言练习题里面查看
十二.函数
1. 函数的概念
在C语言中我们⼀般会见到两类函数:• 库函数• 自定义函数
2. 库函数
2.2 库函数的使用方法
2.3 函数的语法形式
- ret_type fun_name(形式参数)
- {
- }
• ret_type 是函数返回类型• fun_name 是函数名• 括号中放的是形式参数• { }括起来的是函数体
3. 形参和实参
3.1 实参
实参称为实际参数,简称实参。 实际参数就是真实传递给函数的参数。
3.2 形参
3.3 实参和形参的关系
4.函数的声明和定义
例如我们在调用我们写的函数时,我们将函数的定义放在函数main()函数的后边,那么将无法运行。
解决办法:在mian函数前面,就是函数调用之前先声明⼀下 某某 这个函数,声明函数只要交代清楚:函数名,函数的返回类型和函数的参数就能正常编译了。
例:
5. 多个文件(很重要,可以隐藏文件赚钱)
//函数的定义int Add(int x, int y){return x+y;}
//函数的声明int Add(int x, int y);
test.c
#include <stdio.h>#include "add.h"int main(){int a = 10;int b = 20;//函数调用int c = Add(a, b);printf("%d\n", c);return 0;}
6.static 和 extern 函数
• 修饰局部变量• 修饰全局变量• 修饰函数
extern 是用来声明外部符号的
在了解 static 和 extern 之前说⼀下:作用域和生命周期。
上面第二章2.4说过了
6.1static函数延长生命周期,改变结果
//代码1#include <stdio.h>void test(){int i = 0;i++;printf("%d ", i);}int main(){int i = 0;for(i=0; i<5; i++){test();}return 0;}
/代码2#include <stdio.h>void test(){//static修饰局部变量static int i = 0;i++;printf("%d ", i);}int main(){int i = 0;for(i=0; i<5; i++){test();}return 0;}
- 结果是 1 1 1 1 1
- 结果是 1 2 3 4 5
6.2全局变量被static修饰
extern 函数
十三.函数递归
13.1递归的定义
#include <stdio.h>
int main()
{
printf("hehe\n");
main();//main函数中⼜调⽤了main函数
return 0;
}
13.2递归的思想
把⼀个大型复杂问题层层转化为⼀个与原问题相似,但规模较小的子问题来求解;直到⼦问题不能再 被拆分,递归就结束了。所以递归的思考方式就是把大事化小的过程。递归中的递就是递推的意思,归就是回归的意思
递归的经典例子
#include <stdio.h>
int Fact(int n)
{
if(n==0)
return 1;
else
return n*Fact(n-1);
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fact(n);
printf("%d\n", ret);
return 0;
}
代码实现:
int Fib(int n)
{
int a = 1;
int b = 1;
int c = 1;
while(n>2)
{
c = a+b;
a = b;
b = c;
n--;
}
return c;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fib(n);
printf("%d\n", ret);
printf("\ncount = %d\n", count);
return 0;
}
十四.struct 结构体
C语言已经提供了内置类型,如:char、short、int、long、float、double等,但是只有这些内置类型还是不够的,假设我想描述学生,描述⼀本书,这时单⼀的内置类型是不行的。描述⼀个学生需要名字、年龄、学号、身高、体重等;描述⼀本书需要作者、出版社、定价等。C语⾔为了解决这个问题,增加了结构体这种自定义的数据类型,让程序员可以自己创造适合的类型。
结构是⼀些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量,如:标量、数组、指针,甚⾄是其他结构体
14.1结构体的声明
struct tag
{
member-list;
} variable-list;
例:描述一个学生结构体
- 特别注意:结构体最后的分号不能省略
struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
}; //分号不能丢
14.2结构体变量的定义和初始化
//代码1:变量的定义
struct Point
{
int x;
int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
//代码2:初始化。
struct Point p3 = {10, 20};
struct Stu //类型声明
{
char name[15];//名字
int age; //年龄
};
struct Stu s1 = {"zhangsan", 20};//初始化
struct Stu s2 = {.age=20, .name="lisi"};//指定顺序初始化
//代码3
struct Node
{
int data;
struct Point p;
struct Node* next;
}n1 = {10, {4,5}, NULL}; //结构体嵌套初始化
struct Node n2 = {20, {5, 6}, NULL};//结构体嵌套初始化
14.3结构体成员访问操作符
#include <stdio.h>
struct Point
{
int x;
int y;
}p = {1,2};
int main()
{
printf("x: %d y: %d\n", p.x, p.y);
return 0;
}
2.结构体成员的间接访问
#include <stdio.h>
struct Point
{
int x;
int y;
};
int main()
{
struct Point p = {3, 4};
struct Point *ptr = &p;
ptr->x = 10;
ptr->y = 20;
printf("x = %d y = %d\n", ptr->x, ptr->y);
return 0;
}