1、什么是C语言?
C语言:面向过程的计算机编程语言,效率高、更接近底层、运行速率快,更多地用于PC端,不适合做业务逻辑(淘宝、购买商品等)。
C++、JAVA:面向对象的计算机编程语言。
2、第一个C语言程序
#include <stdio.h>
int main()
{
printf("hello bit!/n");
return 0;
}
//解释
//main函数是程序的入口
//一个工程中main函数有且仅有一个
调试!
生成-清理-重新生成
Debug中.exe是生成的可执行
编写源代码的最终目的:通过编译器,形成.exe(编译器的功能:C->.exe)
main函数开始,函数返回值为int,函数参数列表暂时为空,main为入口函数
3、数据类型
为什么会有数据类型?
计算机是为了解决人的问题,人的数据有临时数据(体重)、全局数据(性别),不同的人有不同的数据,数据本身有大小,需要被存储,C语言为了能够记录、保存数据,就有了数据类型。
char //字符数据类型
short //短整型
int //整型
long //长整型
long long //更长的整型
float //单精度浮点数
double //双精度浮点数
每种类型的大小是多少?
#include <stdio.h>
int main()
{
printf("%d\n", sizeof(char));
printf("%d\n", sizeof(short));
printf("%d\n", sizeof(int));
printf("%d\n", sizeof(long));
printf("%d\n", sizeof(long long));
printf("%d\n", sizeof(float));
printf("%d\n", sizeof(double));
return 0;
}
注意:存在这么多的类型,其实是为了更加丰富地表达生活中的各种值。
类型的使用:
char ch = 'w';
int weight = 120;
int salary = 20000;
#include <stdio.h>
int main()
{
char a = 'A'; //初始化(开辟空间、将值写入)
a = 'B'; //赋值
int b;
short c;
float f;
double d = 3.1415;
printf("%c\n", a);
printf("%if\n", d);
return 0;
}
初始化与赋值
初始化:开辟空间;赋值:将B填入空间中(存储空间角度)
4、变量、常量
生活中有些值不变(圆周率、性别、身份证号码、血型),有些直是可变的(年龄、体重、薪资)
4.1 定义变量的方法
int age = 150;
float weight = 45.5f;
char ch = 'w';
4.2 变量的分类
局部变量:临时性,只能在函数内使用。临时变量=局部变量=自动变量
全局变量
#include <stdio.h>
int global = 2019;//全局变量
int main()
{
int local = 2018;//局部变量
//下面定义的global会不会有问题?
int global = 2020;//局部变量
printf("local = %d\n", local);
printf("global = %d\n", global);
return 0;
}
总结:上面的局部变量global变量的定义没有问题,当局部变量和全局变量同名的时候,局部变量优先使用。不推荐在临时变量定义全局变量的同名变量。
4.3 变量的使用
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
int sum = 0;
printf("请输入数据:");
scanf("%d %d", &a, &b);//&:取变量的地址
sum = a + b;
printf("%d + %d = %d\n", a, b, sum);
return 0;
}
//输入语句:scanf
//输出语句:printf
4.4 变量的作用域和生命周期
作用域(scope):程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。
局部变量的作用域是变量所在的局部范围
全局变量的作用域是整个工程。
生命周期:变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段
局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束
全局变量的生命周期是:整个程序的生命周期
#include <stdio.h>
int main()
{
int i = 0;
for (; i < 10; i++) {
int j = 100;
printf("in: i: %d, j: %d\n", i, j);
}
printf("out: i: %d\n", i);
}
代码块:j只能在这个代码块内使用
4.5 常量
C语言中的常量和变量的定义的形式有所差异。
C语言中的常量分为以下几种:
字面常量
#include <stdio.h>
int main()
{
10;
'b';
"hello bit";
3.14;
}
是可以编出来的,但是不能直接使用,每次都得写3.14
#include <stdio.h>
int main()
{
int a = 10;
int c = 'b';
char* s = "hello bit";//char本质也是int
printf("%d, %c, %s\n", a, c, s);
}
const修饰的常变量
#include <stdio.h>
int main()
{
const int a = 10;
a = 20;//不能被修改!
printf("%d\n", a);
}
#include <stdio.h>
int main()
{
const int a = 10;
printf("%d\n", a);
}
#define定义的标识符常量
#include <stdio.h>
#define M 100
int main()
{
int a = M;
printf("%d\n", a);
printf("%d\n", M);
M = 1000;//不行,M是定义的新符号,即常量
}
#include <stdio.h>
#define M 100
int main()
{
int a = M;
printf("%d\n", a);
printf("%d\n", M);
}
枚举常量
#include <stdio.h>
enum Sex
{
MALE,
FEMALE,
SECRET
};
5、字符串+转义字符+注释
5.1 字符串
"hello bit.\n"
这种由双引号(Double Quote)引起来的一串字符称为字符串字面值(String Literal),或者简称字符串。
注:字符串的结束标志是一个\0的转义字符。在计算字符串长度的时候\0是结束标志,不算做字符串内容。
C标准:C90,没有字符串类型,但是有保存字符串的方案(2种)
(1)字符数组保存字符串
#include <stdio.h>
char str[] = "hello world";//可以直接写在里面
int main()
#include <stdio.h>
int main()
{
char str1[] = "abcdefg";
char str2[] = { 'a', 'b', 'c' };
printf("%s\n", str1);
printf("%s\n", str2);
}
“”默认有\0,{}没有\0会出现乱码.
#include <stdio.h>
int main()
{
char str1[] = "abcdefg";
char str2[] = { 'a', 'b', 'c', '\0'};
printf("%s\n", str1);
printf("%s\n", str2);
}
5.2 转义字符
转义字符:转变意思,通过\完成,其本质是特殊转字面
- \? 在书写连续多个问号时使用,防止他们被解析成三字母词
- \' 用于表示字符常量'
- \\ 用于表示一个反斜杠,防止它被解释为一个转义序字符
- \a 警告字符,蜂鸣
- \b 退格符
- \f 进纸符
- \n 换行
- \r 回车
- \t 水平制表符
- \v 垂直制表符
- \ddd ddd表示1~3个八进制的数字。如:\130 X
- \xdd dd表示2个十六进制数字。如:\x30 0
在屏幕上打印',在屏幕上打印一个字符串"
#include <stdio.h>
int main()
{
printf("%c\n", '\'');
printf("%s\n", "\"");
}
#include <stdio.h>
int main()
{
printf("%d\n", strlen("abcdef"));
printf("%d\n", strlen("c:\test\328\test.c"));
// c : \t e s t \32 8 \t e s t . c
}
\0不占长度,但是占空间,strlen是长度,sizeof是空间
\n换行:回车+换行,换到下一行
\r回车:回到下一行的最开始
#include <stdio.h>
int main()
{
printf("姓名\t年龄\t性别\n");
printf("张三\t18\t男\t");
}
6、注释
代码中有不需要的代码可以直接删除,也可以注释掉。代码中有些代码比较难懂,可以加一下注释文字。
C语言风格的注释 /*xxxxxx*/ 缺陷:不能嵌套注释
C++风格的注释 //xxxxxx 可以注释一行也可以注释多行
批量化注释:
全部选中:Ctrl+k Ctrl+c
去掉:Ctrl+k+u
7、选择语句
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
printf("你是否要写代码?");
int flag = 0;
scanf("%d", &flag);
if (flag == 1)
{
printf("找到好工作");
}
else
{
printf("放弃,回家卖红薯\n");
}
return 0;
}
语法:默认是从上到下依次按顺序执行(顺序结构)
分支结构:if判断
条件判断:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int age = 0;
scanf("%d", &age);
if (age >= 18) {
printf("你已经成年了!\n");
}
else {
printf("你还没有成年!\n");
}
return 0;
}
8、循环语句
所有语言都有顺序结构、循环结构、分支结构
for循环:
#include <stdio.h>
int main()
{
int i = 0; //条件初始化,只初始化一次
for (; i < 10; i++) { //条件判断、条件更新,for循环有三个条件(;;)
printf("hello:%d\n", i); //执行语句
}
}
死循环:
#include <stdio.h>
#include <windows.h>
int main()
{
int i = 0;
for (;;) {
printf("hello:%d\n", i);
Sleep(1000);
}
}
while循环:
#include <stdio.h>
int main()
{
int i = 0; //条件初始化
while(i < 10){ //条件判断
printf("hello:%d\n", i);
i++; //条件更新
}
}
死循环:
#include <stdio.h>
#include <windows.h>
int main()
{
int i = 0;
while(1){
printf("hello:%d\n", i);
Sleep(1000);
}
}
do while循环:
#include <stdio.h>
#include <windows.h>
int main()
{
int i = 0;
do {
printf("hello:%d\n", i);
i++;
} while (i < 10);
}
死循环:
#include <stdio.h>
#include <windows.h>
int main()
{
int i = 0;
do {
printf("hello:%d\n", i);
Sleep(1000);
} while (1);
}
循环语句示例:
#include <stdio.h>
int main()
{
printf("加入比特!\n");
int count = 0;
while (count <= 20000) {
printf("coding...:%d\n", count);
count++;
}
if (count > 20000) {
printf("获得了一个好offer!\n");
}
else {
printf("再继续努力!\n");
}
}
9、函数
函数是默认有返回值的,默认返回值为整数(整型)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
printf("请输入两个数#");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
int z = x + y;
printf("result = %d\n", z);
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int MyAdd(int x, int y) {
int z = x + y;
return;
}
int main()
{
printf("请输入两个数#");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
int z = MyAdd(x, y); //将参数传递给最开始的函数
printf("result = %d\n", z);
}
最开始是实现逻辑,下面一部分是业务逻辑,将实现逻辑与业务逻辑进行解耦,便于进行代码维护。
一个简单的计算器:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int MyAdd(int x, int y) { //函数的返回值、函数的名称、函数的形参列表
int z = x + y; //函数体
return z;
}
int MySub(int x, int y) { //函数是默认有返回值的,返回值为整型
int z = x - y;
return z;
}
int MyMul(int x, int y) {
int z = x * y;
return z;
}
int MyDiv(int x, int y) { //函数的返回值、函数的名称、函数的形参列表
if (y == 0) { //函数体:只有括号,则为空函数;若没有函数体,则叫做函数声明(函数可以没有内容,但必须有花括号)
printf("warning : div zero!\n");
return -1; //代表一种错误信息
}
int z = x / y;
return z;
}
void Menu() //不需要返回值,用void:占位符
{
printf("#################################\n");
printf("## 1. ADD 2. Sub ##\n");
printf("## 3. Mul 4. Div ##\n");
printf("#################################\n");
printf("Please Select");
}
int main() {
Menu();
int select = 0;
scanf("%d", &select);
int x = 0;
int y = 0;
if (select >= 1 && select <= 4) { //&&:且(逻辑语)
printf("请输入两个数#");
scanf("%d %d", &x, &y);
int result = 0;
if (select == 1) { //一定要改为==,=代表的是赋值
result = MyAdd(x, y); //函数调用:实参
}
else if (select == 2) {
result = MySub(x, y);
}
else if (select == 3) {
result = MyMul(x, y);
}
else {
result = MyDiv(x, y);
}
printf("result = %d\n", result);
}
else {
printf("你输入的选项有误,请重新输入!");
}
}
函数:一堆代码的集合,可以理解成是一个小一点的程序,函数是一个过程,也叫子程序。
函数名:数字、字母、下划线,要做到见名知意。
首字母大写:MyDiv(大驼峰)
变量的定义:单词+下划线
若不想有返回值,则用viod:占位符
形参和实参:
#include <stdio.h>
#include <windows.h>
void MyShow(int a, int b) { //形参 在函数调用时要发生形参实例化
printf("MyShow: a的地址: %p, b的地址: %p\n", &a, &b);
printf("%d, %d\n", a, b);
}
int main()
{
int a = 10;
int b = 20;
printf("main: a的地址: %p, b的地址: %p\n", &a, &b); //一个变量只有一个地址,不重复
MyShow(a, b); //实参
return 0;
}
结论:函数调用形参实例化要发生临时拷贝。
10、数组:相同数据类型的集合
10.1 数组定义
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5 };
int i = 0;
for (; i < 10; i++) {
printf("arr[%d]: %d\n", i, arr[i]);
}
return 0;
}
int arr[] = { 1,2,3,4,5 }; //可以不定义个数
10.2 数组的下标
C语言规定数组的每个元素都有一个下标,下标是从0开始的。数组可以通过下标来访问。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int arr[10] = {0}; //如果数组10个元素,下标范围是0-9
return 0;
}
#include <stdio.h>
int main()
{
int arr[] = {1,2,3,4};
int num = sizeof(arr) / sizeof(arr[0]); //整个数组的大小/数组第一个元素的大小
int i = 0; //为什么下标为0?都可以,任何数组0下标一定存在
for (; i < num; i++) {
printf("%d\n", arr[i]);
}
return 0;
}
数组下标不能是变量。
10.3 数组的使用
#include <stdio.h>
int main()
{
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
for (i = 0; i < 10; i++) {
printf("%d", arr[i]);
}
printf("\n");
return 0;
}
11、操作符
算数操作符
+ - * / %
int main()
{
int a = 10;
int b = 3;
printf("%d\n", 10 / 3);
}
结果为3:余
int main()
{
int a = 10;
int b = 3;
printf("%d\n", 10 % 3);
}
结果为1:模
移位操作符
>> 右移 <<左移
int main()
{
int a = 10;
printf("%d\n", a>>1);
}
结果为5
10=2^3+2^1=0000 0000 0000 0000 0000 0000 0000 1010
右移1= 0000 0000 0000 0000 0000 0000 0000 0101 =2^2+2^0 = 5
int main()
{
int a = 83;
a = a >> 2;
printf("%d\n", a>>2);
printf("%d\n", a);
// 83=64+16+2+1 = 2^6+2^4+2^1+2^0 = 1010010 = 0000 0000 0000 0000 0000 0000 0101 0010
//>>2 = 0000 0000 0000 0000 0000 0000 0001 0100
// = 10100 = 2^4+2^2 = 20
}
右移相当于除2,本身不修改a值。
单目操作符
! 逻辑反操作- 负值+ 正值& 取地址sizeof 操作数的类型长度(以字节为单位)~ 对一个数的二进制按位取反-- 前置、后置 --++ 前置、后置 ++* 间接访问操作符 ( 解引用操作符 )( 类型 ) 强制类型转换
int main()
{
printf("%d\n", 10 & 6);
}
// 10 = 8 + 2 = 2^3+2^1 = 1010
// 6 = 4 + 2 = 2^2+2^1 = 0110
// 按位与:对等比特位要相同 -> 2
int main()
{
printf("%d\n", 10 ^ 6);
}
// 10 = 8 + 2 = 2^3+2^1 = 1010
// 6 = 4 + 2 = 2^2+2^1 = 0110
// 按位异或:相异为真,相同为假 1100 -> 12
int main()
{
printf("%d\n", 10 | 6);
}
// 10 = 8 + 2 = 2^3+2^1 = 1010
// 6 = 4 + 2 = 2^2+2^1 = 0110
// 按位或:有真则为真 1110 -> 14
复合操作符
a = a + 20; 简写 a += 20;
涉及到赋值都这样写,类似的还有 a -=20 a/=20 a%=20 a^=20 a|=20 a&=20
逻辑反 !
int main()
{
printf("%d\n", !10);
}
int main()
{
printf("%d\n", !-10);
}
结果为0(假)
int main()
{
printf("%d\n", !0);
}
结果为1(真)
int main()
{
int flag = 1;
if (!flag) {
printf("hello bit!\n");
}
else {
printf("hello world!\n");
}
}
结果为hello world!
~:对一个数的二进制进行按位取反
int main()
{
printf("%u\n", ~0); //u是结果
}
0000 0000 0000 0000 0000 0000 0000 0000
1111 1111 1111 1111 1111 1111 1111 1111
++:分为前置++和后置++
int main()
{
int a = 10;
++a; //a++ 结果都是11
printf("%d\n", a);
}
int main()
{
int a = 10;
int b = ++a; //先++再赋值b,结果为11
printf("%d\n", a);
}
int main()
{
int a = 10;
int b = a++; //先将a赋值b再++,结果为10
printf("%d\n", b);
}