💖 技术宅,拯救世界!
🎁作者:@ecember
🎁专栏:《从0开始——C语言》
🎁 对读者的话:相信奇迹的人本身和奇迹一样伟大
🌹感谢大家的点赞 和关注 🌹,如果有需要可以看我主页专栏哟💖 |
⚡1.前言
从现在开始我们就正式踏入C语言的学习咯,在本篇博客中,博主将先带大家认识C语言基本的语法以及各种类型说明,所以本片博客将是我们学习C语言的基础,有了这个基础我们才能搞懂后面的知识。(以下内容均在vs2022中编译哦)。💖
🌠1.1什么是C语言?
C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。
🌀1.1.1计算机语言的发展
低级——高级
ANSI C
ISO K&R C89/C90 C98 C99… C11…
C语言——面向过程,C++ && java——面向对象。
🌀1.1.2常见编译器
其编译器主要有Clang、Gcc、WIN - TC、SUBLIME、MSVC、Turbo C等。
⚡2.第一个C语言程序
#include<stdio.h>
int main()
{
printf("I want to join MHY.\n");
printf("Hello miHoYo!");
return 0;
}
运行截图如下
🌠2.1主体函数的书写规范
//main - 主函数
// main函数是程序的入口,有且仅有一个
//
//f10 - 逐过程
//
int main()//推荐写法
{
return 0;
}
void main()//古老写法不推荐
{
}
int main(void)//明确告诉你返回值为空
{
}
main()//错误写法
{
}
🌠2.2第一个函数printf
#include<stdio.h>
int main()
{
printf("hello bit\n");
printf("hello bit\n");
printf("hello bit\n");‘、
printf("hello bit");
return 0;
}
printf函数的作用是在屏幕上打印括号内的内容,同时需注意一定要包含头文件。
🌠2.3数据类型
🌀2.3.1计算机的内存单位
从小——到大
1 bit位——byte字节(8bit)——KB(1024byte)——MB——GB——TB——PB。
🌀2.3.2 C语言的数据类型
数据类型符号 | 数据类型 | 所占空间 |
---|---|---|
char | 字符数据类型 | 1个字节 |
short | 短整型 | 2个字节 |
int | 整型 | 4个字节 |
long | 长整型 | 4个字节 |
long long | 更长的整型 | 8个字节 |
float | 单精度浮点型 | 4个字节 |
double | 双精度浮点型 | 8个字节 |
我们不妨来验证一下它们所占的空间。
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;
}
其中sizeof是用来计算内存的运算符,注意不能用来计算字符串长度。此外sizeof(long)>=sizeof(int)。
⚡3.变量,常量
顾名思义:变量:可变的量。常量:不变的量。
🌠3.1定义变量与常量
变量又分为全局变量和局部变量。
int num = 1000;//全局变量
int main()
{
int a = 10;//局部变量(优先)
char b = 'w';//字符型变量
float weight = 99.6f;//单浮点型变量
printf("%d\n", num);
return 0;
}
🌠3.2变量的命名
🌠3.3 变量的分类
int num = 1000;//全局变量
int main()
{
int num = 10;//局部变量(优先)
char a = 'w';
float weight = 99.6f;
printf("%d\n", num);
return 0;
}
我们看到定义了两个num变量,那么该以谁优先呢?
结果显而易见当全局变量和局部变量同时存在且相同时,以局部变量优先。
🌠3.4 变量的使用
//求两个整数的和
int main()
{
int num1 = 0;
int num2 = 0;
//输入
scanf("%d %d", &num1, &num2);
int sum = num1 + num2;
//输出
printf("%d\n", sum);
return 0;
}
注意这里我们使用了scanf输入函数,这是C语言的函数,而在vs中不支持此函数,如果要使用需在代码开头加上#define _CRT_SECURE_NO_WARNINGS
拓展延伸:如何在文件内使用另一个文件内声明的全局变量?
//test_1文件
extern int a;
void test()
{
printf("3:a = %d\n", a);
}
int main()
{
printf("1:a = %d\n", a);
{
printf("2:a = %d\n", a);
}
test();
return 0;
}
//test_2文件
int a = 1000;
这里我们使用了extern使得原本在test_2内定义的全局变量用在了test_1文件中。
🌠3.5 变量的作用域和生命周期
🌀3.5.1作用域
作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不总是有效/可用的而限定这个名字的可用性的代码范围就是这个名字的作用域。
1.局部变量的作用域是变量所在的局部范围。
2.全局变量的作用域是整个工程。
🌀3.5.2生命周期
变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段。
局部变量的生命周期:进入作用域生命周期开始,出作用域生命周期结束。
全局变量的生命周期:整个程序的生命周期。
🌠3.6常量
🌀3.6.1字面常量
字面意思就是数字,字符,字符串等直接写出来的如1, 2, ‘w’,30,3.14,“abcdef”等。
🌀3.6.2 const 修饰的常变量
int main()
{
const int num = 100;
num = 200;
printf("%d\n", num);
return 0;
}
从运行结果可以看出const指定的对象为不可修改的常变量。注意我这里说的是常变量!=常量。
那么我们来看看究竟为什么是常变量呢?
我们知道定义数组时,数组的空间一定会是个常量,由此我们可用数组来验证const指定的变量是不是常量。
int main()
{
//数组
const int n = 10;//其中n依然还是变量;
int arr[n] = { 1,2,3,4 };
// 数组验证
return 0;
}
由此可见,const指定的对象依然还是变量。
🌀3.6.3 #define定义的标识符常量
#define MAX 1000
int main()
{
//3. #define 定义的标识符常量
int a = MAX;
printf("%d\n", a);
int arr[MAX];
return 0;
}
由于其可以对数组空间进行分配,故说明#define定义的为常量。
🌀3.6.4 枚举常量
enum Sex
{
MALE,//0
FEMALE,//1
SECRET//2
};
int main()
{
//枚举----一一列举
//男女,颜色
enum Sex s = MALE;
enum Sex s1 = FEMALE;
enum Sex s2 = SECRET;
printf("%d %d %d", s, s1, s2);
return 0;
}
枚举常量是由关键字enum定义的,其中默认从0开始,并以1开始递增·,我们可以人为修改第一个枚举常量的值从而影响后面的值。
思考:如果我们将MALE的值改为4,那么输出是什么?
那我们将FEMALE的值改为5,输出也会是4,5,6吗?
由此可见,我们只能从前面修改枚举常量的值来影响后面的值,不能通过修改前面的值来影响其之前的值。
⚡4.字符及注释
🌠4.1字符
凡是能从键盘上直接打出来的称谓字符,如%^&&,使用是需加上‘ ’,如’A’ ‘3’ ‘4’。
int main()
{
char ch = 'a';
printf("%c\n", ch);
return 0;
}
🌠4.2 ASCII码
由于数据在计算机中的存储和表示都是二进制的,所以说每个字符都有一个对应的ASCII值,常见的ASCII值如下:‘a’——97,‘b’——98,‘0’——48,‘A’——65,字符串结束标志‘\0’——0.
ASCII码表
🌠4.3 字符串
这种由双引号引起来的一串字符称为字符串字面值,或者简称字符串,如“abcdef”。
注意:字符串的结束标志是一个 \0 的转义字符。在计算字符串长度的时候 \0 是结束标志,不算作字符串内容。
int main()
{
char arr1[] = "abcdef";
char arr2[] = { 'a','b','c','d','e','f' };
printf("%s\n%s", arr1,arr2);
return 0;
}
这里按理来说应该打印出两行abcdef才对,但是第二行出现了一堆不知所以的字符,为什么呢?
🌀4.3.1 隐藏的 ‘\0’
我们打开窗口调试
这里我门很清楚的看到arr1数组最后多了个‘\0’,而arr2数组中却没有,这就是问题的根源所在,一个字符串必须要有结束标志,否则程序就会一直读下去直到读到结束字符。
🌀4.3.2 ‘\0’的应用
小科普:strlen()函数可以用来计算字符串长度,即结束标志‘\0’之前的字符个数相加。
int main()
{
char arr1[] = "abcdef";
char arr2[] = { 'a', 'b', 'c', 'd', 'e', 'f' };
printf("%d\n", strlen(arr1));
printf("%d\n", strlen(arr2));
printf("%d\n", strlen("abc\0def"));
printf("%d\n", strlen("abc"));
return 0;
}
我们来仔细想想输出结果是什么呢?
这就是’\0’的威力,第二行打印结果完全取决于后续的‘\0’的位置,因此打印出来是个随机值。第三行也是一样,尽管输入了六个字符,但由于结束标志的存在,程序读到第三个字符即终止。
🌠4.4 转义字符
🌀4.4.1 引入
#include <stdio.h>
int main()
{
printf("c:\code\test.c\n");
return 0;
}
当然打印出来是c:\code\test.c,可实际是这样吗?我们运行试试。
哎嘿,这是怎么回事呢?我们注意到其中有许多带‘\’的符号,这是不是和‘\0’,‘\n’一样是特殊的转义字符呢?
🌀4.4.2 转义字符表
下面是一组常见转义字符表。
转义字符 | 释义 |
---|---|
\? | 在书写连续多个问号时使用,防止他们被解析成三字母词 |
\' | 用于表达字符常量 |
\" | 用于表示一个字符串内部的双引号 |
\\ | 用于表示一个反斜杠,防止他被解释为一个转义序列符 |
\a | 警告字符,蜂鸣 |
\b | 退格符 |
\f | 进纸符 |
\n | 换行 |
\r | 回车 |
\t | 水平制表符 |
\v | 垂直制表符 |
\ddd | ddd表示1 - 3个八进制数字。如:\130x |
\xdd | dd表示2个十六进制数字。如:\x30 0 |
🌀4.4.3 转义字符实例
int main()
{
printf("%s\n", "hello\?\?");//输出结果为hello??
printf("%s\n", "\' \" \\");//输出结果为 ' " \
printf("\a\a\a\a");//电脑发出警告蜂鸣
printf("%s\n", "你好\b啊");//退格符,结果为你啊
printf("%s\n", "你好 \r啊");//将电脑光标定位到开头 结果为啊好
printf("你\t好\n");//水平制表符表示空八个空格,输出结果为你 好
printf("%d\n", '\130');//三个八进制数(8^2*1+8*3+8^0*0)=88 若输出为字符,则为字符x(ASCII码)
printf("%d\n", '\x30');//三个十六进制数(16*3+1*0)=48 若输出为字符,则为字符0
return 0;
}
练习
int main()
{
printf("c:\test\628\test.c\n");
printf("该字符串的长度是:");
printf("%d\n", strlen("c:\test\628\test.c"));
return 0;
}
揭晓答案
这里大家千万要注意\628这个地方,8不是八进制数了,所以/62是一个字符,8是一个字符。
🌠4.5 注释
1. 代码中有不需要的代码可以直接删除,也可以注释掉.
2. 代码中有些代码比较难懂,可以加一下注释文字.
int main()
{
//printf("hello\n");——C++注释风格推荐
/*printf("hello\n"); ——C语言注释风格不推荐*/
return 0;
}
注释有两种风格:
C语言风格的注释 /xxxxxx/缺陷:不能嵌套注释
C++风格的注释 //xxxxxxxx可以注释一行也可以注释多行
⚡5.选择语句
如果你好好学习,校招时拿一个好offer,走上人生巅峰。如果你不学习,毕业等于失业,回家卖红薯。这就是选择!C语言也是一样。
int main()
{
int input = 0;
printf("进入大学学习\n");
printf("你要好好学习吗?(1/0)\n");
scanf("%d", &input);
if (input == 1)
printf("好offer\n");
else
printf("卖红薯\n");
//if() else if() else
return 0;
}
这里我们只是给大家简单介绍选择语句的模式,后续将为大家详细介绍。
⚡6.循环语句
有些事必须一直做,比如我日复一日的讲课,比如大家,日复一日的学习。
上图就是一种典型的循环结构。
int main()
{
int line = 0;
printf("进入大学\n");
while (line < 20000)
{
printf("写代码\n");
line++;
}
if (line == 20000)
printf("好offer\n");
return 0;
}
C语言实现循环的方式是通过while,for,do while,等循环实现的,这里我们只介绍一种,后续将为大家进一步介绍。
⚡7.函数
数学中的函数:f(x)=2*x+1,我们知道函数可以让复杂问题简单化,C语言也是如此。
🌠7.1 函数的架构
我们先来看看实现求和的代码。
int main()
{
int sum1, sum2;
scanf("%d%d", &sum1, &sum2);
int sum = sum1 + sum2;
printf("%d\n", sum);
return 0;
}
相必这么简单的代码大家一眼就看懂了,那么问题来了,怎么用函数来实现求和的过程呢?
//函数
//int 结果返回类型
//Add 函数体
int Add(int x, int y)//函数体定义根据输入确定是整形还是其他类型
{
return x + y;
}
int main()
{
int num1 = 0;
int num2 = 0;
int sum = 0;
scanf("%d%d", &num1, &num2);
//求和
//sum = num1 + num2;
sum = Add(num1, num2);
printf("%d\n", sum);
return 0;
}
🌠7.2 函数的好处
函数可以给我们的代码书写带来巨大的方便,主要体现在代码复用以及简化代码方面,而且友友们工作的时候大工程都是封装多个函数逐一实现。
⚡8.数组
🌠8.1数组的定义
如果我们要存放1-10,或者1-100,该怎么存放?
//数组-存放同一类型的数据
//int arr[10] = {1,2,3,4,5,6,7,8,9,10};
//char ch[5] = { 0 };//不完全初始化,其余元素被默认初始化为0;
//char ch2[] = { ‘a’, ‘b’, ‘c’ };//普遍写法;
//char ch[]=“abcdef”//字符串
🌠8.2数组的下标
我们可以通过下标来访问数组中的任何元素。
int main()
{
int a = 1;
int b = 2;
int c = 3;
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//\0 的ASCII码是0;
printf("%d\n", arr[8]);
//一定不能越界访问
return 0;
}
我们给出打印结果。
可以看出我们成功访问了数组的第九号元素,因为数组的下标一定是从0开始的所以我们访问arr[8]也就是第九号元素。那么如果我们访问10之后的元素呢?
这里系统打印出了一组随机值,也就是出现了数组越界这种情况,这种情况对初学者来说很常见,我们做题时编译器会出现段错误的提示,这种就可能是数组越界了。
🌠8.3数组的使用
有了数组,一些大规模数据问题也就得到了解决。这里我们先试试数组的打印。
int main()
{
int arr[10] = { 0 };
int i = 0;
//输入10个值给数组
while (i <= 9)
{
scanf("%d", &arr[i]);//循环结构实现数组值得输入
i++;
}
//输出数组中的10个值
i = 0;
while (i < 10)
{
printf("%d ", arr[i]);//循环结构实现数组值的输出
i++;
}
return 0;
}
OK!,大功告成。
⚡9.结语
好了,到这我们的初识C语言上篇已经接近尾声了,后续我将会持续更新下篇,学习永无止境,就会永远只会留给有准备的人。希望我的博客对大家有所帮助,如果喜欢的可点赞+收藏哦,也随时欢迎大家在评论区及时指出我的错误。