一晃今年又开始了,作为一个失意的中年技术男,现在的心境真的是五味杂陈。赶紧写一篇吧,我怕过了这个点,今年就在没有那个心情去写了。

因为是基础嘛,从事软件开发以来c或者c++相关的东西断断续续 也刷了差不多一遍。中间看的书差不多有 c++游戏编程入门教程,vc++深入详解, c++ primer plus ,c程序设计语言。

c语言和c++以及一些其它高级语言的区别

与其它高级语言 比如c# java 相比c++是一个开放式的开源的所谓的众人拾柴火焰高的解决方式,只规定了基本的语法和约定 各种其他,比如编译器都由各个厂商自己去实现 比如多线程没有  各种只要跟操作系统接口相关的  那么说白了还是不能跨平台的 所谓的跨平台只是说这个基本语法和格式约定 在各个平台编译大差不差。实际上这个众人拾柴还是火焰没高起来 。c++在服务器或者嵌入式 以及底层算法上用的是比较多的 ,但是Windows上快速的应用层开发,不如微软c#那种一揽子方案来得舒服。

然后说说c++与纯c,纯c里面并不支持string 也不支持include<string> 可以说是刀耕火种的地步了 ,std库不用说更是不支持。其实想想c++已经算是比较高级方便的了 。说归说 接触了c51  msp430 stm32 还是能够发现一些端倪的 ,从最初引导芯片进入首条指令执行的那几句汇编 为萌芽 到后面不断的喂指令 不断的循环 地址偏移 ,跳转 判断, 开启了 后面以软件为主题的这个学科  编程嘛 条件判断嘛 内存嘛 数据嘛   进程嘛  巴拉巴拉,像极了世界的一生二二生三三生万物,人类在芯片上运行程序进行流程控制 计算机最基础的雏形 关键之处 也在于此,汇编或者c语言正符合这种最初级的需求,你会发现原来这就是所谓的裸机编程 并没有操作系统上层一堆的东西参与也没有库,一切都是刀耕火种 ,不是说它多么的高深多么难 其实就是这么的纯粹而已。 基于它的这种直接内存控制的高效机制 所以做底层算法的 大多还是用C/C++这玩意儿。

对于初学者某些东西如果开始选择难的如果弄不出来是很容易消磨人的意志的 ,作为普通人谁不想拖拖鼠标就能做出来功能呢。还有所谓的动态内存分配,在c++里所谓的动态内存分配概念就是一个函数大括号下来里面运行的东西叫自动变量 放在栈上 ,括号结束即从栈上清除掉,动态内存就仅是指new出来的东西 方法运行结束了还没消失的东西,搞了单片机那一套后才发现  也就几百行的程序就算大程序了 并且也根本用不上所谓的动态内存分配 ,根据cpu的时钟频率 ,简单粗暴的的单线程循环 代表cpu的一个运转周期 ,恍然觉得最简单的编程原来可不就是这样吗,值处理和指针 以及位操作 有那么一点奇技淫巧存在。以前只知道有些使用位操作编写方式可提高运行效率,不觉得所以然,在资源局限的单片机上做了工作 以及对那种机制了解过后 就会明白为啥可以提高运行效率,以及逼着你必须那样去做。

一些基本上手

纯c嘛,万事当然从printf开始,来一段printf基本操作

 1 void PrintTest(){
2 int a = 23;
3 //打印一个整数 ,注意这里有陷阱哈 ,如果是一个浮点数35.1并不会输出35 而是0
4 printf("%d\n", a);
5
6 //纯c里面并不支持string 也不支持include<string>
7 //string str1("sdfdfdf33444");
8 //纯c打印字符串
9 char * str1 = "nihao\0";
10 printf("%s\n", str1);
11 //运算任意一侧有浮点数 运算之前整数操作会被转为浮点数
12 printf("%f\n", 5.0 / 9);
13 printf("%3.2f\n", 643.1415926);
14 //%02X 格式化为16进制 比如0x05 不足2位的前面会以0补齐
15 printf("%02X\n", 5);
16 printf("Hello world!\n");
17 }

用惯了高级语言 新手老是说不就是输出个字符串吗 c怎么这么麻烦,咋个又不对了,所谓万事开头难,然后是人类编程流程控制最基础的 数字 文本转换了 ,还有文本的格式化 ,对不对 ,有木有。

 1 void PrintTest2(){
2
3 //纯c里面利用sprintf_s实现类似stringFormat的效果
4 //标准c里是支持sprintf的 ,vc里面不支持 使用sprintf_s作为替代
5 int a = 23;
6 char buff[8] = { 0 };
7 sprintf_s(buff, "%d个\0", a);
8 printf("%s\n", buff);
9
10 //c语言中的字符串拼接
11 //str1+str2; c语言里并不能这样
12 //字符串数组方式
13 char str1[] = "hello ";//可以换成 char * str1=
14 char str2[] = "world";//可以换成 char * str2=
15 char str3[20] = "";//这个不能换
16 strcat_s(str3, str1);//strcat_s也是作为strcat的替代
17 strcat_s(str3, str2);
18 printf("%s\n", str3);
19
20 //数字转字符串
21 int num = 4568;
22 char number[15];
23 _itoa_s(num, number, 10);//_itoa_s也是作为itoa的替代
24 printf("%s\n", number);
25 //字符串转数字
26 char * number2 = "8957";
27 int number33;
28 number33=atoi(number2);
29 printf("parse Int :%d\n", number33);
30
31 //上面的两种都可以用下面的解决方案
32 //但是注意str5必须要先分配固定内存,也不能使用char
33 char * str4 = "hello\0";
34 int num1 = 6749;
35 char str5[20];
36 sprintf_s(str5, "%s - %d", str4, num1);
37 printf("%s", str5);
38
39 }

然后c语言的一些基础的,比如函数体内的变量 在函数结束前销毁称之为自动变量,基本的变量赋值 表达式运算条件判断 。函数每次运行互相独立的 ,这些不用多说了吧。 注意上面代码的注释vc里面的某些函数跟标准c有一些出入 ,但是区别不大。注意sprintf的使用可以实现一些灵活的格式化字符串效果。然后你会发现c都是最基础的字节和地址操作 ,深入思考后如果你愿意上面类似的字符转数字函数你可以自己写一个 可不就是每个字节ascii码比对然后转换成二进制位吗,高级语言字符串 是怎么封装来的 ,单片机里的指令  内存 数据 ,c太原始了 由不得 你不去思考 它的本质了。c里的数组   地址偏移  指针 几个东西总是左右游走 亦数组亦指针 模棱两可,深入理解后你就会发现指针 包括高级语言的.点操作符 本质就是地址偏移 数组可以理解为一组连续偏移的变量。有时候通过这种机制实现灵活的内存操作 以及利用一些奇技淫巧实现一些高效的位操作,这既是纯c被人诟病的地方,也是它优势的地方 看你怎么理解咯。总之一句话就是 根据内存地址进行内存数据操作。基于以上 所以c++很大一部分都是在讲动态内存分配,c很大一部分是在讲位操作和指针。上代码:

玩出花的指针:

 1 void PointerVoidTest(){
2 //指针也要确定数据类型 才能输出它本来的值 ,这里有一点技巧 void指针可以跟其它指针转换
3 int * pi1;
4 int nn1 = 762;
5 void * pv1;
6 pv1 = &nn1;
7 //void指针转换的正确例子 ,(int *) 仅仅时转换成了一个int指针 前面还要加* 才输出本来的数
8 printf("%d aa", *(int *)pv1);
9 }
10 void PointerTest(){
11 //我们平常编程写的字符常量"aaa" 这种的 或者参数 也是一种预分配内存形式的指针
12
13 //指针地址也可以进行比较== 类似于意思看是不是同一个引用
14
15 //c语言中地址算术运算是一致且又规律的 讲指针数组 和地址的算术运算集成在一起是该语言的一大优点
16 //函数定义中 char*s 和char s[] 是等价的
17
18 int a1[3][5];
19 int *b[10];
20 //对于C语言的初学者来说,很容易混淆二维数组与指针数组之间的区别,比如上面例子中
21 //int a[3][5]; 是一种正规数组做法
22 //int *b[10] 是一个10元素的数组 每个元素是一个int指针,还必须初始化每个指针的指向
23 //才是一个二维数组 ,比第一种的优势是 每个元素可以指向长短不一的数组 比如字符串应用
24 //指针数组
25 char * mname[] = { "illegal month", "jan", "feb", "mar" };
26 //二维数组 除第一维以外其他维必须指明长度
27 char mname2[][15] = { "illegal month", "jan", "feb", "mar" };
28
29 int ar[] = { 4, 5, 7, 6 };
30 int * pa;
31 pa = ar;//等同于 pa=&ar[0];
32 printf("%d--\n", *(pa + 1));//等同于ar[1] 注意这个微秒的区别 地址偏移
33 //*(pa+i) 为对应数组下标i的值
34 printf("%d--\n", *(ar + 1));//同样等同于 ar[1]
35 printf("%d--\n", pa[1]);
36 //看指针和数组偏移量 指针玩出花儿来
37 //p++ 如果是int那么地址也会增加对应的int类型字节长度 p89页
38 //void* 一种通用指针
39 //指针是能够存放一个地址的一组存储单元 通常是4字节
40 //指针还要确认他指向什么 以便知道长度 和后续操作 int * 代表指向int的指针
41 //&是取地址符 ,取变量对象的地址
42 //并不是说用了指针就等于动态内存分配 maloc new 那些才算,其实单片机编程中很少动态内存分配
43 //一元运算符*是简介寻址或简介引用运算符 当他用于指针时 将访问指针所指向的对象
44
45 //c语言的类型 数组 声明的前缀的组合非常灵活
46 int x = 1, y = 2, z[10];
47 int *ip;
48 ip = &x;//现在ip指向x
49 y = *ip;//现在y=1;
50 //ip=&z[0];//现在IP只想z[0] //传数组变量其实是一种变相的方式
51 (*ip)++;//圆括号是必须的 否则 对地址进行+1运算
52 printf("%d--\n", *ip);
53
54 z[0] = 5;
55 z[1] = 8;
56 ip = &z[0];
57 *(ip++);
58 printf("%d--\n", *ip);
59
60 //把一个指针复制给另一个指针
61 //指针也是变量 就是一个地址 直接使用 而不必使用间接引用符&
62 int *iq;
63 iq = ip;
64 printf("%d--\n", *iq);
65
66 printf("%d--\n", iq);//指针变量保存的地址 可以发现跟printf("%d--\n", ip);是一样的
67 printf("%d--\n", &iq);//而这个变量本身又保存在那个地址?
68
69 printf("------------------------------\n");
70 *(&iq) = 0;//
71 printf("%d++\n", z[1]);
72 printf("%d--\n", iq);//指针指向的地址变为0
73 //现在已经是一个野指针 出来的int是不知道是什么值的,严重时程序会崩溃
74 //printf("%d--\n", *iq);
75 printf("%d--\n", &iq);//指针变量本身的地址依然客观存在
76 }

高阶的指针数组 地址偏移量操作本质 以及void指针类型转换

接下来是一个二维数组和指针相结合操作的例子:

 1 void reIniAr2(int *b[])//unsigned short*a[],
2 {
3 for (int i = 0; i<2; i++){
4 for (int j = 0; j<2; j++){
5 //b[i][j] = 666;
6 *(*(b + i) + j) = 444;
7 }
8 }
9 }
10 void arr2dTest(){
11 //数组已经声明后 不用想这种歪门子再去整体赋值 ,无论咋个都是不行的,必须的老老实实一个一个重新赋值
12 //然后另外一个c的数组长度并不允许通过变量确定 必须通过define 或者常量确定,
13 //网上评论说c99编译可以 int alen=3;int ar[alen]
14 //fqTab=&fqTab2;
15 //指针方式的2维数组处理
16 int a1[] = { 786, 894 };
17 int b1[] = { 377, 945 };
18 //这种方式是都支持的 两个一维数组地址 结合成指针形式的二维数组
19 int * ar[] = { &a1[0], &b1[0] };
20 //这种方式codeblocks只是不会报错 但是后续操作会有莫名问题 vs2013直接不支持
21 //int * ar[] = { {1,2}, {3,4} };
22 //*(*(ar + 1) + 0) = 444;
23 reIniAr2(ar);
24 //ar[0][0] = 555; 既可以通过这种方式访问元素,也可以通过下面这种地址偏移方式访问
25 //但是下面这种理解起来需要花一番功夫
26 printf("%d--bb\n", *(*(ar + 0) + 0));
27 //但是由这种过度呢 *号代表取指针指向的本来的东西
28 printf("%d--bb\n", *(ar + 0)[0]);
29
30 //当然下面才是一种简便 正常数组的用法,上面的不强求
31 int a2[2][2] = {0};
32 a2[0][0] = 734;
33 a2[0][1] = 841;
34 printf("%d--b2\n", a2[0][0]);
35 printf("%d--b2\n", a2[0][1]);
36 }

然后是一个二维数组操作的示例,注意通过传递void类型的指针 ,我们却把当成 unsigned short类型进行解析 以及地址偏移的技巧i*2是因为short占2字节

 1 void OffSetDataReplaceFqTab(int adstart, int adcount, char * fqSegment)
2 {
3 for (int i = 0; i < adcount; i++)
4 {
5 int offsetStart = adstart + i - 10;
6 // "/"取高位 "%"取低位 c语言的常规套路 这里的使用也是这个理念
7 int iOffset = offsetStart / 11;//行偏移
8 int jOffset = offsetStart % 11;//列偏移
9 //低索引是高位
10 //unsigned short beadd = (((char)(fqSegment[i * 2]))<<8) | (char)(fqSegment[i * 2+1]);
11 //这样也是对的
12 //以前没写对因为没有深刻理解fqSegment[i] 就是代表那个元素&fqSegment[i]才是地址
13 //(unsigned short *) 只是转换成了指针 前面还要再加*
14 //当然转换成usigned short的过程也是根据我们常见计算机系统来的也就是Intel的little字节序
15 //低索引是低位 高索引是高位
16 //数组相当于连续定义的指针
17 //基本理念上就跟嵌入式视频c语言地址赋值的那个地方一致
18 //unsigned short beadd = *(unsigned short *)&fqSegment[i*2];
19 unsigned short beadd = *(unsigned short *)(fqSegment+(i*2));
20 fqTab[iOffset][jOffset] = beadd;
21 }
22 }
23
24 char pia[10] =
25 {
26 0x01, 0x01,
27 0xff, 0xff,
28 0x01, 0x01,
29 0, 3,
30 0, 4 };
31 OffSetDataReplaceFqTab(21, 5, &pia[0]);

然后是另一个void类型指针转换的例子

1 void PointerVoidTest(){
2 //指针也要确定数据类型 才能输出它本来的值 ,这里有一点技巧 void指针可以跟其它指针转换
3 int * pi1;
4 int nn1 = 762;
5 void * pv1;
6 pv1 = &nn1;
7 //void指针转换的正确例子 ,(int *) 仅仅时转换成了一个int指针 前面还要加* 才输出本来的数
8 printf("%d aa", *(int *)pv1);
9 }

还有常见的对指定内存地址赋值:

 1 void PointerTest2(){
2 //常规指针操作
3 int num1 = 4331;
4 int *ip;
5 ip = &num1;
6 //指向的地址本身也是一个门牌编号可以用int表示
7 int add1 = (int)ip;
8 printf("%d--\n", *ip);
9 printf("%d--\n", ip);
10 printf("%d--\n", add1);
11
12 int *ip2;
13 //然后我们把这个门牌号反过来又变成一个指针
14 ip2 = (int*)add1;
15 //进而通过*ip 即可实现所谓的对指定地址进行赋值
16 //汇编里面这是基础操作,也是面试时经常喜欢考的一道c语言基础题
17 *ip2 = 9745;
18 printf("--------------------\n");
19 printf("%d--\n", num1);
20 printf("%d--\n", *ip);
21 printf("%d--\n", ip);
22 printf("%d--\n", add1);
23 }

函数指针(又叫委托 或者回调方法  巴拉巴拉)

接下来是函数指针 的用法 ,我们最开始得弄两个参数一样的方法 作为同等级调用区分示例 对吧

 1 //函数指针简单使用 概念类似c#的委托
2 int method1(int a){
3 printf("method11:%d\n",a);
4 return 0;
5 }
6
7 int method2(int a){
8 printf("method22:%d\n",a);
9 return 0;
10 }

然后是调用套路,普通的形参定义 void method1(int a) ,这里int a  就代表形参了。当参数是函数委托的时候 int(*delegate)(int ) 就成了函数指针, *号括号后面再括号 就认为是方法引用,不要问为什么 ,就这么不讲道理 姑且死记硬背吧。

1 void calback1(int(*delegate)(int ))//接受返回一个int的函数委托
2 {
3 int a = delegate(3);
4 printf("a=%d--\n", a);
5 }
6 calback1(method2);

手持表里面一种函数指针的用法

 1 //定义委托 接受int形参 返回int的方法
2 typedef int (del)( int);
3
4 //委托数组
5 del *ds[] = {
6 method1,
7 method2
8 };
9 //调用委托数组元素进行执行
10 //以前只知道数组元素可以通过索引取出,没听说过元素还能“执行”真是神奇
11 ds[0](555);
12 ds[1](777);

枚举和结构体

定义

 1 //枚举统一声明方式 别忘了typedef
2 typedef enum
3 {
4 one,
5 two,
6 three,
7 } num;
8
9 //结构体的统一声明方式 //别忘了typedef
10 //typedef 类型定义
11 typedef struct
12 {
13 int x;
14 int y;
15 } pp;
16 //typedef int numb1; //typedef char*string ; 书上说标准库的string就是这么来的
17 //c语言的理念是一个处处能找到源头的东西的 ,只要你想深挖
18 //还有一些基本常识,='A'与=65 在编译器级别 是一样的没区别
19 //int cr ='A';//cr=65
20
21 //位字段
22 struct
23 {
24 unsigned int is_keyword : 1;//关键点就在于这个 :1 吗?
25 unsigned int is_extern : 1;
26 unsigned int is_static : 1;
27 } flags;

结构体调用测试,还有以前面试的时候被问题及sizeof 问题的时候还以为 c内部有什么封装 ,到头来发现也就是结构体内所有元素数据类型加起来的总长度而已,还有个新鲜的可能是以前没有接触过的那就是位字段操作,在单片机上使用很适合

 1 void strAndEnumTest(){
2 //枚举测试
3 num n1 = one;
4 num n2 = two;
5
6 if (n2 == two)
7 printf("ok--a\n");
8
9 printf("%d--a\n", sizeof(pp));//pp结构体里有两个int 输出8
10 //结构体 ,指针的访问方式 ->箭头运算符
11 //struct pp p3={1,3};
12 pp p2 = { 5, 8 }; //c的结构有点数组的味道,跟c#不一样 注意不要写成{ x=5,y=8}
13 //c语言和c++中的很多时候 初始化 没有new xxx 这样的,不像c#
14 //就是类指针和实例 的概念 习惯一下就好了
15 pp * p1;
16 p1 = &p2;
17 p1->x = 2;//等价 (*p1).x
18
19 //struct pp or1,*p3 //c的声明组合真的非常灵活
20 printf("%d--\n", p1->x);
21 printf("%d--\n", p2.x);//普通的直接的访问方式
22 printf("%d--\n", p2.y);//
23 printf("%d--a\n", sizeof(p2));
24
25
26 //位字段操作
27 //果然是可以的 直接整体方便的方式进行位操作
28 //除了51单片机的基础例子有类似的方式 ,其他时候其实并没有见用过
29 flags.is_keyword = 0;//2进制的第2位
30 flags.is_extern = 1;//2进制的第1位
31 flags.is_static = 0;//2进制的第0位
32 printf("%d\n", flags);//还可以整体输出合并的值
33 }

一篇关于c语言的大补帖的更多相关文章

  1. PayPal高级工程总监:读完这100篇论文 就能成大数据高手(附论文下载)

    100 open source Big Data architecture papers for data professionals. 读完这100篇论文 就能成大数据高手 作者 白宁超 2016年 ...

  2. 面霸篇:Java 集合容器大满贯(卷二)

    面霸篇,从面试角度作为切入点提升大家的 Java 内功,所谓根基不牢,地动山摇. 码哥在 <Redis 系列>的开篇 Redis 为什么这么快中说过:学习一个技术,通常只接触了零散的技术点 ...

  3. 20155308《信息安全系统设计基础 嵌入式C语言课堂考试补博客

    20155308<信息安全系统设计基础 嵌入式C语言课堂考试补博客 知识点 置位 ?bits = bits | (1 << 7) ; /* sets bit 7 */ bits |= ...

  4. Spark GraphX宝刀出鞘,图文并茂研习图计算秘笈与熟练的掌握Scala语言【大数据Spark实战高手之路】

    Spark GraphX宝刀出鞘,图文并茂研习图计算秘笈 大数据的概念与应用,正随着智能手机.平板电脑的快速流行而日渐普及,大数据中图的并行化处理一直是一个非常热门的话题.图计算正在被广泛地应用于社交 ...

  5. C语言8大经典排序算法(1)

    算法一直是编程的基础,而排序算法是学习算法的开始,排序也是数据处理的重要内容.所谓排序是指将一个无序列整理成按非递减顺序排列的有序序列.排列的方法有很多,根据待排序序列的规模以及对数据的处理的要求,可 ...

  6. 添物零基础到大型全栈架构师 不花钱学计算机及编程(预备篇)— C语言编程基础

    ​C语言介绍 C语言基本是每个编程人员必学的一面语言,很好掌握,是理解编程的关键.很多编程语言基于其编写或者基于此语言的衍生品编写. C语言是人机交互的一个基础语言之一,虽然是之一,单一般其实就是唯一 ...

  7. Go语言 | 哪些大公司在用go语言?

    Go大概09年面世以来,已经8年了,也算是8年抗战.在这8年中,已经有很多公司开始使用Go语言开发自己的服务,甚至完全转向Go开发,也诞生了很多基于Go的服务和应用,比如Dokcer.k8s等,现在我 ...

  8. R语言和大数据

    #安装R语言R3.3版本会出现各种so不存在的问题,退回去到R3.1版本时候就顺利安装.在安装R环境之前,先安装好中文(如果没有的话图表中显示汉字成框框了)和tcl/tk包(少了这个没法安装sqldf ...

  9. 第四篇:R语言数据可视化之折线图、堆积图、堆积面积图

    折线图简介 折线图通常用来对两个连续变量的依存关系进行可视化,其中横轴很多时候是时间轴. 但横轴也不一定是连续型变量,可以是有序的离散型变量. 绘制基本折线图 本例选用如下测试数据集: 绘制方法是首先 ...

  10. 第一篇:R语言数据可视化概述(基于ggplot2)

    前言 ggplot2是R语言最为强大的作图软件包,强于其自成一派的数据可视化理念.当熟悉了ggplot2的基本套路后,数据可视化工作将变得非常轻松而有条理. 本文主要对ggplot2的可视化理念及开发 ...

随机推荐

  1. 解决IDEA中xxxMapper.xml文件表名,字段爆红问题

    我们在编写xxxMapper.xml中sql代码的时候有时会出现表名不会提示,表名爆红等情况,这个一般是没有设置IDEA的sql解析范围,下面是我遇到问题时候的解决办法 1.打开IDEA设置 2.选择 ...

  2. 【一步步开发AI运动小程序】九、姿态辅助调试桌面工具的使用

    随着人工智能技术的不断发展,阿里体育等IT大厂,推出的"乐动力"."天天跳绳"AI运动APP,让云上运动会.线上运动会.健身打卡.AI体育指导等概念空前火热.那 ...

  3. csv导出特殊字符问题

    昨天听到隔壁组讨论说按照逗号分割implode导出到csv文件,传递文件数据给别人的时候,别人按照都好explode分割回来多一个单元格,他们调查了一下发现是内容里面就是有逗号导致的,居然就这么卡住了 ...

  4. Python通过requests模块处理form-data请求格式

    1.安装 requests_toolbelt 模块,引入该模块下的 MultipartEncoder 2.在 请求体 中使用该模块函数,请求头中增加对应参数值 from requests_toolbe ...

  5. Memcached笔记——(一)安装&常规错误&监控

    08年的时候接触过Memcached,当时还对它的客户端产品嗤之以鼻,毕竟手工代码没有各种ORM原生XML配置方便.尽管如此,Memcached现在已经成了服务器架构里不可或缺的一部分! 相关链接:  ...

  6. 基于docker的常用服务搭建

    使用docker搭建相关服务: 1. MySQL服务 1) 拉取镜像 docker pull mysql:5.7 # 拉取 mysql 5.7 docker pull mysql # 拉取最新版mys ...

  7. Ubuntu下xrdp登陆故障解决方案

    故障描述: Ubuntu使用xrdp远程桌面运行一段时间后,出现登陆错误: xrdp_mm_process_login_response: login failed 原因分析: 远程桌面没有正确关闭所 ...

  8. C#实现控制台显示动态进度条百分比

    C#实现控制台显示动态进度条 前言 private static void Main(string[] args) { bool isBreak = false; ConsoleColor color ...

  9. StarBlog博客Vue前端开发笔记:(4)使用FontAwesome图标库

    前言 在现代前端开发中,图标已成为构建用户友好界面的重要元素.Font Awesome 是全球最流行的图标库之一,提供了大量的矢量图标,支持多种平台和框架.无论是网站.应用程序,还是管理面板,Font ...

  10. 拦截烂SQL,解读GaussDB(DWS)查询过滤器过滤规则原理

    本文分享自华为云社区<GaussDB(DWS)查询过滤器过滤规则原理与使用介绍>,作者: 清道夫. 1. 前言 适用版本:[9.1.0.100(及以上)] 查询过滤器在9.1.0.100之 ...