C ++ 学习之 C 语言基础 (一)_damon c代码-程序员宅基地

技术标签: C 语言基础  自学总结  

工作需要近期接触 C++ 利用空闲时间整理输出一下个人总结,希望给一起学习的伙伴们分享一下学习历程,也是鞭笞自己不能有所放松.因个人能力有限,如有错误的地方或是意见还请留言指出,谢谢

C语言基础 (一)

1.C语言概述

1.1 第一个C语言程序:hello world

1.1.1 编写C语言代码:hello.c

#include <stdio.h> //包含头文件  std标准库 io入输出库
int main(void)
{
    printf("hello world! \n");
	return 0; 
}

1.1.2 通过gcc编译C代码

编译命令格式:

gcc [-option1] ... <filename>
g++ [-option1] ... <filename>
  • 命令、选项和源文件之间使用空格分隔
  • 一行命令中可以有零个、一个或多个选项
  • 文件名可以包含文件的绝对路径,也可以使用相对路径
  • 如果命令中不包含输出可执行文件的文件名,可执行文件的文件名会自动生成一个默认名,Linux平台为a.out,Windows平台为a.exe

1.1.3 代码分析

  1. include头文件包含
  • include的意思是头文件包含,#include <stdio.h>代表包含stdio.h这个头文件
  • include< > 与 #include ""的区别:
    1. < >表示系统系统库
    2. " "标志自定义库
  1. main函数
    • 一个完整的C语言程序,是由一个、且只能有一个main()函数(又称主函数,必须有)和若干个其他函数结合而成(可选)。
    • main函数是C语言程序的入口,程序是从main函数开始执行。
  2. {}括号,程序体和代码块
    • {}叫代码块,一个代码块内部可以有一条或多条语句
    • C语言美剧可执行代码都是";"号结尾
    • 所有的#开头的行都是预编译指令,预编译指令行结尾是没有分号的
    • 所有的可执行语句必须是在代码块里面
  3. 注释
    • // 行注释
    • /* 内容 */ 块注释
  4. printf函数
    • printf(“hello wotld\n”); // \n的意思是换行`
  5. return 语句
    • return 代表函数执行完毕,返回 return 代表函数的终止
    • 函数的返回值要与main定义前面的类型相对应,如代码中 return 0 和 int main()

1.2 system 函数

1.2.1 system 函数的使用

#include <stdlib.h>
int system(const char *command);
// 功能: 在已经运行的程序中执行另一个外部程序
// 参数: 外部可执行程序名字或命令
// 返回值: 成功:不同系统返回值不一样  失败:通常为 -1

示例代码:

#include <stdio.h>
#include <stdlib.h>

int main()
{
	//system("calc"); //windows平台
	system("ls"); //Linux平台, 需要头文件#include <stdlib.h>

	return 0;
}

1.3 C 语言编译过程

1.3.1 C语言编译步骤

C代码编译成可执行程序经过4步:

1)预处理:宏定义展开、头文件展开、条件编译等,同时将代码中的注释删除,这里并不会检查语法

2)编译:检查语法,将预处理后文件编译生成汇编文件

3)汇编:将汇编文件生成目标文件(二进制文件)

4)链接:C语言写的程序是需要依赖各种库的,所以编译之后还需要把库链接到最终的可执行程序中去

1.3.2 gcc 编译过程

  1. 分布编译
    预处理:gcc -E hello.c -o hello.i
    编 译:gcc -S hello.i -o hello.s
    汇 编:gcc -c hello.s -o hello.o
    链 接:gcc hello.o -o hello_elf

    选项 含义
    -E 只进行预处理
    -S(大写) 只进行预处理和编译
    -c(小写) 只进行预处理、编译和汇编
    -o file 指定生成的输出文件名为 file

  2. 一步编译
    gcc hello.c -o demo

1.3.3 找找程序所依赖的动态库

  1. Linux平台下,ldd可执行程序,如:ldd hello

  2. Windows平台下,需要相应的软件(Depends.exe)

  3. 数据类型

2.1 常量与变量

2.1.1关键字

C的关键字共有32个

  • 数据类型关键字(12个)
    char, short, int, long, float. double. unsigned. signed, struct, union, enum, void
  • 控制语句关键字(12个)
    if, else, switch, case, default, for, do, while, break, continue, goto, return
  • 储存类关键字(5个)
    auto, extern, register, static, const
  • 其他关键字(3个)
    sizeof, typedef, volatile

2.1.2 数据类型

数据类型的作用:编译器预算对象分配内存空间的大小.

数据类型

  • 基本类型
    • 整形: int, short, long
    • 字符型: char
    • 实型(浮点型): 单精度 float 双精度 double
  • 构造类型
    • 数组类型
    • 结构类型 struct
    • 联合类型 union
    • 枚举类型 enum
  • 指针类型 (char *, int * ,int **)

2.1.3 常量

常量:

  • 在程序运行过程中,值不能被改变的量
  • 常量一般出现在表达式或复制语句中

格式:

  1. const 数据类型 常量名
  2. "#difine 常量名 值
    注意:通过#define定义的常量是根据值来匹配数据类型的,对于C语言 const修饰的常量是不安全的,可以通过指针来修改

2.1.4 变量

  1. 变量(又称"只读变量")
    变量
    • 在程序运行过程中,值可以改变
    • 变量在使用前必须定义,定义变量前必须有相应的数据类型
      标识符命名规则:
    • 标识符不能是关键字
    • 标识符只能由字母,数字,下划线组成
    • 第一个字符必须为字母或下划线
    • 标识符中字母区分大小写
      变量特点:
    • 变量在编译时为其分配相应的内存空间
    • 可以通过变量的名字和地址访问相应内存
  2. 声明和定义的区别:
    • 声明变量不需要建立储存空间

    • 定义变量需要建立储存空间
      #include <stdio.h>

      int main()
      {
      //extern 关键字只做声明,不能做任何定义
      //声明一个变量a,a在这里没有建立存储空间
      extern int a;
      a = 10; //err, 没有空间,就不可以赋值

      int b = 10; //定义一个变量b,b的类型为int,b赋值为10

      return 0;
      }

2.1.5 使用示例

#include <stdio.h>
#define MAX 10 //声明了一个常量,名字叫MAX,值是10, 常量的值一旦初始化就不能改变

int main()
{
    int a; //定义课一个变量,类型为int,名字叫a
    const int b = 10; //定义一个const常量,名为叫b,值为10
    // b = 11; //err,常量的值不能改变

	// MAX = 100;	//err,常量的值不能改变

	a = MAX;//将abc的值设置为MAX的值
	a = 123;

	printf("%d\n", a); 

	return 0;
}

2.2 进制

十进制 以正常数字1-9开头,如123
八进制 以数字0开头,如0123
十六进制 以0x开头,如0x123
二进制 C语言不能直接书写二进制数

#include <stdio.h>

int main()
{
	int a = 123;		//十进制方式赋值
	int b = 0123;		//八进制方式赋值, 以数字0开头
	int c = 0xABC;	//十六进制方式赋值

	//如果在printf中输出一个十进制数那么用%d,八进制用%o,十六进制是%x
	printf("十进制:%d\n",a );
	printf("八进制:%o\n", b);	// %o,为字母o,不是数字
	printf("十六进制:%x\n", c);// %x 或 %X

	return 0;
}

术语 含义
bit(比特) 一个二进制代表一位,一个位只能表示0或1两种状态。数据传输是习惯以“位”(bit)为单位。
Byte(字节) 一个字节为8个二进制,称为8位,计算机中存储的最小单位是字节。数据存储是习惯以“字节”(Byte)为单位。
WORD(双字节) 2个字节,16位
DWORD 两个WORD,4个字节,32位
1b 1bit,1位
1B 1Byte,1字节,8位
1k,1K 1024
1M(1兆) 1024k, 1024*1024
1G 1024M

2.3 计算机内存数值储存方式

2.3.1 原码

一个数的原码(原始二进制码)有以下特点

  • 最高位作为符号位,0表示正,1表示负
  • 其他数值部分就是数值本身绝对值得二进制数
  • 负数的原码是在其绝对值的二进制数基础上,最高位变为1
    十进制数 原码
    +15 0000 1111
    -15 1000 1111
    +0 0000 0000
    -0 1000 0000

原码表示法简单易懂,但是原码不便于加减运算

2.3.2 反码

  • 对于正数,反码与原码相同
  • 对于负数,符号位不变,其他部分取反(1变0,0变1)
    十进制数 反码
    +15 0000 1111
    -15 1111 0000
    +0 0000 0000
    -0 1111 1111

2.3.3 补码

在计算机系统中,数值一律用补码来存储

补码特点:

  • 对于正数,原码,反码,补码相同
  • 对于负数,补码为他的反码加1
    十进制数 补码
    +15 0000 1111
    -15 1111 0001
    +0 0000 0000
    -0 0000 0000

2.3.4 补码的意义

示例:计算9-6的结果

以原码方式相加:

十进制数 原码
9 0000 1001
-6 1000 0110

计算结果为 1000 1111( -15),不正确

以补码方式相加:

十进制数 补码
9 0000 1001
-6 1111 1010

计算结果为 1 0000 0011(最高位的1溢出,剩余8位二进制表示是3) 正确

在计算机系统中,数值一律用补码来存储,主要原因:

  • 统一了零的编码
  • 将符号位和其他位统一处理
  • 将减法运算转变为加法运算(计算机中无减法操作)
  • 两个用补码表示的数相加时,如果最高位(符号位)有进位,则进位被舍弃

2.4 sizeof 关键字

  • sizeof 不是函数,所以不需要包含任何头未见,他的功能是计算一个数据类型的大小,单位为字节

  • sizeof 的返回值为 size_t

  • size_t 类型在32位操作系统下湿unsigned int 是一个无符号的整数

    #include <stdio.h>

    int main()
    {
    int a;
    int b = sizeof(a);//sizeof得到指定值占用内存的大小,单位:字节
    printf(“b = %d\n”, b);

      size_t c = sizeof(a);
      printf("c = %u\n", c);//用无符号数的方式输出c的值
    
      return 0;
    

    }

格式:

  • int value =sizeof(变量名);
  • int value = sizeof(数据类型) sizeof 数据类型

注意:根据32位操作系统获取的数据类型大小

2.5 整形

2.5.1 整型变量的输出

#include <stdio.h>

int main()
{
	int a = 123;	//定义变量a,以10进制方式赋值为123
	int b = 0567;	//定义变量b,以8进制方式赋值为0567
	int c = 0xabc;	//定义变量c,以16进制方式赋值为0xabc

	printf("a = %d\n", a);
	printf("8进制:b = %o\n", b);
	printf("10进制:b = %d\n", b);
	printf("16进制:c = %x\n", c);
	printf("16进制:c = %X\n", c);
	printf("10进制:c = %d\n", c);

	unsigned int d = 0xffffffff; //定义无符号int变量d,以16进制方式赋值
	printf("有符号方式打印:d = %d\n", d);
	printf("无符号方式打印:d = %u\n", d);
	return 0;
}

2.5.2 整型变量输入

#include <stdio.h>

int main()
{
	int a;
	printf("请输入a的值:");

	//不要加“\n”
	scanf("%d", &a);

	printf("a = %d\n", a); //打印a的值

	return 0;
}

2.5.3 short, int, long, long long

数据类型 占用空间
short(短整型) 2字节
int(整型) 4字节
long(长整形) Windows为4字节,Linux为4字节(32位),8字节(64位)
long long(长长整形) 8字节

注意:

  • 整型数据在内存中占的字节数与选择的操作系统有关.
  • 当一个小的数据类型赋值给一个大的数据类型,不会出错,因为编译器会自动转化,但是当一个大的类型赋值给一个小的数据类型,那么可能丢失高位

2.5.4 有符号和无符号数区别

  1. 有符号数
    有符号数是最高位为符号位,0代表正数,1代表负数

    定义: signed int a = -1089474374; //定义有符号整型变量a

  2. 无符号数
    无符号数最高为不是符号位,而是数的一部分,无符号数不可能是负数.
    定义:unsigned int a = 3236958022; //定义无符号整型变量a

当写程序要处理一个不可能出现负值的时候,一般用无符号数,这样可以增大数的表达最大值.

  1. 有符号和无符号整形取值范围
    数据类型 占用空间 取值范围
    short 2字节 -32768 到 32767 (-215 ~ 215-1)
    int 4字节 -2147483648 到 2147483647 (-231 ~ 231-1)
    long 4字节 -2147483648 到 2147483647 (-231 ~ 231-1)
    unsigned short 2字节 0 到 65535 (0 ~ 216-1)
    unsigned int 4字节 0 到 4294967295 (0 ~ 232-1)
    unsigned long 4字节 0 到 4294967295 (0 ~ 232-1)

2.6 字符型: char

2.6.1 字符变量的定义和输出

字符型变量用于存储一个单一字符,在C语言中用 char 表示,其中每个字符变量都会占用 1 个字节。在给字符型变量赋值时,需要用一对英文半角格式的单引号(’ ')把字符括起来。

#include <stdio.h>

int main()
{
	char ch = 'a';
	printf("sizeof(ch) = %u\n", sizeof(ch));

	printf("ch[%%c] = %c\n", ch); //打印字符
	printf("ch[%%d] = %d\n", ch); //打印‘a’ ASCII的值

	char A = 'A';
	char a = 'a';
	printf("a = %d\n", a);		//97
	printf("A = %d\n", A);	//65

	printf("A = %c\n", 'a' - 32); //小写a转大写A
	printf("a = %c\n", 'A' + 32); //大写A转小写a

	ch = ' ';
	printf("空字符:%d\n", ch); //空字符ASCII的值为32
	printf("A = %c\n", 'a' - ' '); //小写a转大写A
	printf("a = %c\n", 'A' + ' '); //大写A转小写a

	return 0;
}

2.6.2 自读变量的输入

#include <stdio.h>

int main()
{
	char ch;
	printf("请输入ch的值:");

	//不要加“\n”
	scanf("%c", &ch);
	printf("ch = %c\n", ch); //打印ch的字符

	return 0;
}

2.6.3 转义字符

转义字符 含义 ASCII码值(十进制)
\a 警报 007
\b 退格(BS) ,将当前位置移到前一列 008
\f 换页(FF),将当前位置移到下页开头 012
\n 换行(LF) ,将当前位置移到下一行开头 010
\r 回车(CR) ,将当前位置移到本行开头 013
\t 水平制表(HT) (跳到下一个TAB位置) 009
\v 垂直制表(VT) 011
\ 代表一个反斜线字符"" 092
’ 代表一个单引号(撇号)字符 039
" 代表一个双引号字符 034
? 代表一个问号 063
\0 数字0 000
\ddd 8进制转义字符,d范围0~7 3位8进制
\xhh 16进制转义字符,h范围09,af,A~F 3位16进制

2.6.4 数值溢出

当超过一个数据类型能够存放最大的范围时,数值会溢出.

最高位溢出和符号位溢出的区别:符号位溢出会导致数的正负发生改变,最高位的溢出会导致最高位丢失

2.7 实型(浮点型): float double

实型变量也可以成为浮点型变量,浮点型变量是用来储存小数数值的.在C语言中,浮点型变量分为两种:单精度浮点型(float) 双精度浮点型(double)double类型变量所表示的浮点数比float型变量表示的更精确.

数据类型 占用空间 有效数字范围
float 4字节 7位有效数字
double 8字节 15~16位有效数字

不以 f 结尾的常量是double类型,以f结尾的常量是float类型.

3.运算符与表达式

3.1 常用运算符分类

运算符类型 作用
算术运算符 用于处理四则运算
赋值运算符 用于将表达式的值赋给变量
比较运算符 用于表达式的比较,并返回一个真值或假值
逻辑运算符 用于根据表达式的值返回真值或假值
位运算符 用于处理数据的位运算
sizeof运算符 用于求字节数长度

3.2算术运算符

运算符 术语 示例 结果

  • 正号    	+3         	3        
    
  • 负号    	-3         	-3       
    
  • 加     	10 + 5     	15       
    
  • 减     	10 - 5     	5        
    
  • 乘     	10 * 5     	50       
    

/ 除 10 / 5 2
% 取模(取余) 10 % 3 1
++ 前自增 a=2; b=++a; a=3; b=3;
++ 后自增 a=2; b=a++; a=3; b=2;
– 前自减 a=2; b=–a; a=1; b=1;
– 后自减 a=2; b=a–; a=1; b=2;

3.3 赋值运算符

运算符 术语 示例 结果
= 赋值 a=2; b=3; a=2; b=3;
+= 加等于 a=0; a+=2; a=2;
-= 减等于 a=5; a-=3; a=2;
= 乘等于 a=2; a=2; a=4;
/= 除等于 a=4; a/=2; a=2;
%= 模等于 a=3; a%2; a=1;

3.4 比较运算符

C 语言的比较运算中, "真"用数字 1 表示,"假"用数字 0 表示.

运算符 术语 示例 结果
== 相等于 4 == 3 0
!= 不等于 4 != 3 1
< 小于 4 < 3 0

大于  	4 > 3 	1   

<= 小于等于 4 <= 3 0

= 大于等于 4 >= 1 1

3.5 逻辑运算符

运算符 术语 示例 结果
! 非 !a 如果a为假,则!a为真;如果a为真,则!a为假。
&& 与 a && b 如果a和b都为真,则结果为真,否则为假。
|| 或 a || b 如果a和b有一个为真,则结果为真,二者都为假时,结果为假。

3.6 运算符优先级

优先级 运算符 名称或含义 使用形式 结合方向 说明
1 [] 数组下标 数组名[常量表达式] 左到右 –
() 圆括号 (表达式)/函数名(形参表) –
. 成员选择(对象) 对象.成员名 –
-> 成员选择(指针) 对象指针->成员名 –

2 - 负号运算符 -表达式 右到左 单目运算符
	按位取反运算符 	~表达式          	               	    	     

++ 自增运算符 ++变量名/变量名++
– 自减运算符 --变量名/变量名–

  • 	取值运算符   	*指针变量         	               	    	     
    

& 取地址运算符 &变量名
! 逻辑非运算符 !表达式
(类型) 强制类型转换 (数据类型)表达式 –
sizeof 长度运算符 sizeof(表达式) –

3 / 除 表达式/表达式 左到右 双目运算符

  • 	乘       	表达式*表达式       	               	    	     
    

% 余数(取模) 整型表达式%整型表达式
4 + 加 表达式+表达式 左到右 双目运算符

  • 	减       	表达式-表达式       	               	    	     
    

5 << 左移 变量<<表达式 左到右 双目运算符

  右移      	变量>>表达式       	               	    	     

6 > 大于 表达式>表达式 左到右 双目运算符

= 大于等于 表达式>=表达式
< 小于 表达式<表达式
<= 小于等于 表达式<=表达式
7 == 等于 表达式==表达式 左到右 双目运算符
!= 不等于 表达式!= 表达式

8 & 按位与 表达式&表达式 左到右 双目运算符
9 ^ 按位异或 表达式^表达式 左到右 双目运算符
10 | 按位或 表达式|表达式 左到右 双目运算符
11 && 逻辑与 表达式&&表达式 左到右 双目运算符
12 || 逻辑或 表达式||表达式 左到右 双目运算符

13 ?: 条件运算符 表达式1?表达式2: 表达式3 右到左 三目运算符

14 = 赋值运算符 变量=表达式 右到左 –
/= 除后赋值 变量/=表达式 –
= 乘后赋值 变量=表达式 –
%= 取模后赋值 变量%=表达式 –
+= 加后赋值 变量+=表达式 –
-= 减后赋值 变量-=表达式 –
<<= 左移后赋值 变量<<=表达式 –

= 右移后赋值 变量>>=表达式 –
&= 按位与后赋值 变量&=表达式 –
^= 按位异或后赋值 变量^=表达式 –
|= 按位或后赋值 变量|=表达式 –

15 , 逗号运算符 表达式,表达式,… 左到右 –

3.7类型转换

数据有不同的类型,不同类型数据之间进行混合运算是必然涉及到类型的转换.

转换类型有两种方式:

  1. 自动转换(隐式转换):遵循一定规则,有变异系统自动完成.
  2. 强制类型转换:把表达式的运算结果前值转换成所需的数据类型.

类型转换的原则:占用内存字节数少的类型向占用内存字节数多的类型转换,以保证精度不降低.

3.7.1 隐式转换

#include <stdio.h>

int main()
{
	int num = 5;
	printf("s1=%d\n", num / 2);
	printf("s2=%lf\n", num / 2.0);

	return 0;
}

3.7.2 强制转换

强制类型转换指的是适应强制类型转换运算符,将一个变量或表达式转化成所需的类型,基本语法: (类型说明符) (表达式)

#include <stdio.h>

int main()
{
	float x = 0;
	int i = 0;
	x = 3.6f;

	i = x;			//x为实型, i为整型,直接赋值会有警告
	i = (int)x;		//使用强制类型转换

	printf("x=%f, i=%d\n", x, i);

	return 0;
}
  1. 程序流程结构

4.1 概述

C 语言支持最基本的三种程序运行结构:顺序结构 选择结构 循环结构.

  • 顺序结构: 程序按顺序执行,不发生跳转
  • 选择结构: 依据满足条件,有选择地执行相应功能
  • 循环结构: 依据条件是否满足, 循环多次执行某段代码

4.2 选择结构

4.2.1 if 语句

#include <stdio.h>

int main()
{
	int a = 1;
	int b = 2;

	if (a > b)
	{
		printf("%d\n", a);
	}

	return 0;
} 

4.2.2 if … else 语句

#include <stdio.h>
int main(void)
{
    int a =1;
    int b =2;
    if(a>b)
    {
        printf("%d\n",a)
    }
    else
    {
        printf("%d\n",b)
    }
    return 0
}

4.2.3 if … else if … else

#include <stdio.h>

int main()
{
	unsigned int a;
	scanf("%u", &a);

	if (a < 10)
	{
		printf("个位\n");
	}
	else if (a < 100)
	{
		printf("十位\n");
	}
	else if (a < 1000)
	{
		printf("百位\n");
	}
	else
	{
		printf("很大\n");
	}

	return 0;
}

4.2.4 三目运算符

#include <stdio.h>

int main()
{
	int a = 10;
	int b = 20;
	int c;

	if (a > b)
	{
		c = a;
	}
	else
	{
		c = b;
	}
	printf("c1 = %d\n", c);

	a = 1;
	b = 2;
	c = ( a > b ? a : b );
	printf("c2 = %d\n", c);

	return 0;
}

4.2.5 switch

#include <stdio.h>

int main()
{
	char c;
	c = getchar();

	switch (c) //参数只能是整型变量
	{
	case '1':
		printf("OK\n");
		break;//switch遇到break就中断了
	case '2':
		printf("not OK\n");
		break;
	default://如果上面的条件都不满足,那么执行default
		printf("are u ok?\n");
	}
	return 0;
}

注意:

if条件语句执行效率差, switch 条件语句执行效率高,但是 if 可以判断一个区间 switch用来判断一个值, 三目运算符结构简单明了.

4.3 循环结构

4.3.1 while 语句

#include <stdio.h>

int main()
{
	int a = 20;
	while (a > 10)
	{
		scanf("%d", &a);
		printf("a = %d\n", a);
	}

	return 0;
}

while 语句一般用于不确定循环次数的情况下

4.3.2 do … while 语句

#include <stdio.h>

int main()
{
	int a = 1;
	do
	{
		a++;
		printf("a = %d\n", a);
	} while (a < 10);

	return 0;
}

do … while 语句无论条件是否满足.循环总执行一次

4.3.3 for 语句

#include <stdio.h>

int main()
{
	int i;
	int sum = 0;
	for (i = 0; i <= 100; i++)
	{
		sum += i;

	}

	printf("sum = %d\n", sum);

	return 0;
}

最常使用的循环语句,常用语已知循环出口的情况

4.4 跳转语句 break continue goto

4.4.1 break 语句

在 switch 条件语句和循环语句中可以使用 break 语句:

  • 当他出现在 switch 条件语句中时, 作用是终止某个 case 并挑出 switch 结构.
  • 当他出现在循环语句中,作用是跳出当前内循环语句.
  • 当他出现在嵌套循环语句中,跳出最近的内循环语句.

break 不能直接用于if 的,但是如果在for 里面,是可以用的,就是如果达到条件,就退出for

#include <stdio.h>

int main()
{
	int i = 0;
	while (1)
	{
		i++;
		printf("i = %d\n", i);

		if (i == 10)
		{
			break; //跳出while循环
		}
	}

	int flag = 0;
	int m = 0;
	int n = 0;

	for (m = 0; m < 10; m++)
	{
		for (n = 0; n < 10; n++)
		{
			if (n == 5)
			{
				flag = 1;
				break; //跳出for (n = 0; n < 10; n++)
			}
		}

		if (flag == 1)
		{
			break; //跳出for (m = 0; m < 10; m++)
		}
	}

	return 0;
}

4.3.2 continue 语句

再循环中,如果希望立即终止本次循环,并执行下一次循环,此时就需要食用 continue 语句.

#include<stdio.h>

int main()
{
	int sum = 0;           //定义变量sum

	for (int i = 1; i <= 100; i++)
	{
		if (i % 2 == 0)   //如果i是一个偶数,执行if语句中的代码
		{
			continue;      //结束本次循环
		}
		sum += i;          //实现sum和i的累加
	}

	printf("sum = %d\n", sum);

	return 0;
}

注意: 使用 continue 时要考虑到循环变量自增或自减,避免死循环

4.3.3 goto 语句 (无条件跳转, 尽量少用)

#include <stdio.h>

int main()
{
	goto End; //无条件跳转到End的标识
	printf("aaaaaaaaa\n");

End:
	printf("bbbbbbbb\n");

	return 0;
}

5 .数组和字符串

5.1 概述

在程序设计中,为了方便处理数据,把具有相同类型的若干变量按有序形式组织起来称为数组.

数组就是在内存中连续的相同类型的变量空间,同一个数组所有的成员都是相同的数据类型,同时所有的成员在内存中的地址是连续的.

数组属于狗仔数据类型:

  • 一个数组可以分解为多个数组元素:这些数组元素可以是基本数据类型或构造类型.
  • 安数组元素类型的不同,数组可分为"数值数组,字符数组,指针数组,结构数组等

通常情况下,数组元素下标的个数也称为维数.根据维数的不同,可将数组分为一维数组,二维数组,三维数组等.通常情况下,我们将二位及以上的数组称为多维数组.

5.2 一维数组

5.2.1 一维数组的定义和使用

  • 数组名符合标识符的书写规定

  • 数组名不能与其他变量名相同

  • 方括号" [ ] "中常量表达时表示数组元素的个数

  • 定义数组时" [ ] "内嘴还是常量,使用数组时 " [ ] "既可以是常量也可以是变量

    #include <stdio.h>

    int main()
    {
    int a[10];//定义了一个数组,名字叫a,有10个成员,每个成员都是int类型
    //a[0]…… a[9],没有a[10]
    //没有a这个变量,a是数组的名字,但不是变量名,它是常量
    a[0] = 0;
    //……
    a[9] = 9;

      int i = 0;
      for (i = 0; i < 10; i++)
      {
      	a[i] = i; //给数组赋值
      }
    
      //遍历数组,并输出每个成员的值
      for (i = 0; i < 10; i++)
      {
      	printf("%d ", a[i]);
      }
      printf("\n");
    
      return 0;
    

    }

5.2.2 一位数组的初始化

在定义数组的同时进行赋值,称为初始化.全局数组若不初始化,便一起将其初始化为零.局部数组若不初始化,内容为随机值.

	int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//定义一个数组,同时初始化所有成员变量
	int a[10] = { 1, 2, 3 };//初始化前三个成员,后面所有元素都设置为0
	int a[10] = { 0 };//所有的成员都设置为0

	 //[]中不定义元素个数,定义时必须初始化
	   int a[] = { 1, 2, 3, 4, 5 };//定义了一个数组,有5个成员

求出数组元素个数:

int (size_t) unsigned int 个数 = sizeof(数组名)/sizeof(数组元素 | 数组数据类型)

5.2.3 数组名

数组名是一个地址的常量,代表数组中首元素的地址.

#include <stdio.h>

int main()
{
	int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//定义一个数组,同时初始化所有成员变量

	printf("a = %p\n", a);
	printf("&a[0] = %p\n", &a[0]);

	int n = sizeof(a); //数组占用内存的大小,10个int类型,10 * 4  = 40
	int n0 = sizeof(a[0]);//数组第0个元素占用内存大小,第0个元素为int,4

	int i = 0;
	for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");

	return 0;
}

5.2.3 一维数组应用

  1. 一维数组的最值

    #include <stdio.h>

    int main()
    {
    int a[] = { 1, -2, 3,- 4, 5, -6, 7, -8, -9, 10 };//定义一个数组,同时初始化所有成员变量

     int i = 0;
     int max = a[0];
     for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
     {
     	if (a[i] > max)
     	{
     		max = a[i];
     	}
     }
     printf("数组中最大值为:%d\n", max);
    
     return 0;
    

    }

  2. 一维数组的逆序

    #include <stdio.h>

    int main()
    {
    int a[] = { 1, -2, 3,- 4, 5, -6, 7, -8, -9, 10 };//定义一个数组,同时初始化所有成员变量

     int i = 0;
     int j = sizeof(a) / sizeof(a[0]) -1;
     int tmp;
    
     while (i < j)
     {
     	tmp = a[i];
     	a[i] = a[j];
     	a[j] = tmp;
     	i++;
     	j--;
     }
    
     for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
     {
     	printf("%d ", a[i]);
     }
     printf("\n");
    
     return 0;
    

    }

  3. 冒泡排序

    #include <stdio.h>

    int main()
    {
    int a[] = { 1, -2, 3,- 4, 5, -6, 7, -8, -9, 10 };//定义一个数组,同时初始化所有成员变量

     int i = 0;
     int j = 0;
     int n = sizeof(a) / sizeof(a[0]);
     int tmp;
    
     //1、流程
     //2、试数
     for (i = 0; i < n-1; i++)
     {
     	for (j = 0; j < n - i -1 ; j++)//内循环的目的是比较相邻的元素,把大的放到后面
     	{
     		if (a[j]  > a[j + 1])
     		{
     			tmp = a[j];
     			a[j] = a[j+1];
     			a[j+1] = tmp;
     		}
     	}
     }
    
     for (i = 0; i < n; i++)
     {
     	printf("%d ", a[i]);
     }
     printf("\n");
    
     return 0;
    

    }

5.3 二维数组

5.3.1 二维数组的定义和使用

二维数组定义的一般形式是:

类型说明符 数组名 [常量表达式1][常量表达式2]

其中常量表达式1表示第一维下标的长度,常量表达式2表示第二维下标的长度.

  • 命名规则同一维数组

  • int a[3][4]定义一个 3 行 4 列数组,数组名为 a 其元素类型为整形,该数组的元素个数为 3 * 4 个,二维数组 a 是按行进行存放的,先存放 a[0]行,在存放 a[1]行,并且每行有四个元素,也是一次存放的.

  • 二维数组在概念上是二维的: 其下标在两个方向上变化,对其访问一般需要两个下标.

  • 在内存中并不存在二位数组,二位数组实际的硬件存储器是连续编址的,也就是说内存中只有一维数组,即放完一行之后顺次放入第二行,和一维数组存放方式是一样的.

    #include <stdio.h>

    int main()
    {
    //定义了一个二维数组,名字叫a
    //由3个一维数组组成,这个一维数组是int [4]
    //这3个一维数组的数组名分别为a[0],a[1],a[2]
    int a[3][4];

      a[0][0] = 0;
      //……
      a[2][3] = 12;
    
      //给数组每个元素赋值
      int i = 0;
      int j = 0;
      int num = 0;
      for (i = 0; i < 3; i++)
      {
      	for (j = 0; j < 4; j++)
      	{
      		a[i][j] = num++;
      	}
      }
    
      //遍历数组,并输出每个成员的值
      for (i = 0; i < 3; i++)
      {
      	for (j = 0; j < 4; j++)
      	{
      		printf("%d, ", a[i][j]);
      	}
      	printf("\n");
      }
    
      return 0;
    

    }

5.3.2 二维数组的初始化

//分段赋值 	int a[3][4] = {
   { 1, 2, 3, 4 },{ 5, 6, 7, 8, },{ 9, 10, 11, 12 }};
	int a[3][4] = 
	{ 
		{ 1, 2, 3, 4 },
		{ 5, 6, 7, 8, },
		{ 9, 10, 11, 12 }
	};

	//连续赋值
	int a[3][4] = { 1, 2, 3, 4 , 5, 6, 7, 8, 9, 10, 11, 12  };

	//可以只给部分元素赋初值,未初始化则为0
	int a[3][4] = { 1, 2, 3, 4  };

	//所有的成员都设置为0
	int a[3][4] = {0};

	//[]中不定义元素个数,定义时必须初始化
	int a[][4] = { 1, 2, 3, 4, 5, 6, 7, 8};

5.3.3 数组名

数组名是一个地址的常量,代表数组中首元素的地址

#include <stdio.h>

int main()
{
	//定义了一个二维数组,名字叫a
	//二维数组是本质上还是一维数组,此一维数组有3个元素
//每个元素又是一个一维数组int[4]
	int a[3][4] = { 1, 2, 3, 4 , 5, 6, 7, 8, 9, 10, 11, 12  };

	//数组名为数组首元素地址,二维数组的第0个元素为一维数组
	//第0个一维数组的数组名为a[0]
	printf("a = %p\n", a);
	printf("a[0] = %p\n", a[0]);
	
	//测二维数组所占内存空间,有3个一维数组,每个一维数组的空间为4*4
	//sizeof(a) = 3 * 4 * 4 = 48
	printf("sizeof(a) = %d\n", sizeof(a));

	//测第0个元素所占内存空间,a[0]为第0个一维数组int[4]的数组名,4*4=16
	printf("sizeof(a[0]) = %d\n", sizeof(a[0]) );

	//测第0行0列元素所占内存空间,第0行0列元素为一个int类型,4字节
	printf("sizeof(a[0][0]) = %d\n", sizeof(a[0][0]));

	//求二维数组行数
	printf("i = %d\n", sizeof(a) / sizeof(a[0]));

	// 求二维数组列数
	printf("j = %d\n", sizeof(a[0]) / sizeof(a[0][0]));

	//求二维数组行*列总数
	printf("n = %d\n", sizeof(a) / sizeof(a[0][0]));

	return 0;
}

5.4 多维数组(了解)

多维数组的定义与二维数组类似.

#include <stdio.h>

int main()
{
	//int a[3][4][5] ;//定义了一个三维数组,有3个二维数组int[4][5]
	int a[3][4][5] = { { { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 10 }, { 0 }, { 0 } }, { { 0 }, { 0 }, { 0 }, { 0 } }, { { 0 }, { 0 }, { 0 }, { 0 } } };

	int i, j, k;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 4; j++)
		{
			for (k = 0; k < 5; k++)
			{
				//添加访问元素代码
				printf("%d, ", a[i][j][k]);
			}
			printf("\n");
		}
	}
	return 0;
}

5.5 字符数组与字符串

5.5.1 字符数组与字符串的区别

  • C 语言中没有字符串这种数据类型,可以通过char 的数组来代替

  • 字符串一定是一个 char 的数组, 但 char 的数组未必是字符串

  • 数字0(和字符 ‘\0’ 等价)结尾的 char 数组就是一个字符串, 但如果 char数组没有数字 0 结尾,那么就不是一个字符串, 只是普通字符数组, 所以字符串是一种特殊的 char 的数组.

    #include <stdio.h>

    int main()
    {
    char c1[] = { ‘c’, ’ ', ‘p’, ‘r’, ‘o’, ‘g’ }; //普通字符数组
    printf(“c1 = %s\n”, c1); //乱码,因为没有’\0’结束符

      //以‘\0’(‘\0’就是数字0)结尾的字符数组是字符串
      char c2[] = { 'c', ' ', 'p', 'r', 'o', 'g', '\0'}; 
      printf("c2 = %s\n", c2);
    
      //字符串处理以‘\0’(数字0)作为结束符,后面的'h', 'l', 'l', 'e', 'o'不会输出
      char c3[] = { 'c', ' ', 'p', 'r', 'o', 'g', '\0', 'h', 'l', 'l', 'e', 'o', '\0'};
      printf("c3 = %s\n", c3);
    
      return 0;
    

    }

5.5.2 字符串的初始化

#include <stdio.h>

// C语言没有字符串类型,通过字符数组模拟
// C语言字符串,以字符‘\0’, 数字0
int main()
{
	//不指定长度, 没有0结束符,有多少个元素就有多长
	char buf[] = { 'a', 'b', 'c' };
	printf("buf = %s\n", buf);	//乱码

	//指定长度,后面没有赋值的元素,自动补0
	char buf2[100] = { 'a', 'b', 'c' };
	printf("buf2 = %s\n", buf2);

	//所有元素赋值为0
	char buf3[100] = { 0 };

	//char buf4[2] = { '1', '2', '3' };//数组越界

	char buf5[50] = { '1', 'a', 'b', '0', '7' };
	printf("buf5 = %s\n", buf5);

	char buf6[50] = { '1', 'a', 'b', 0, '7' };
	printf("buf6 = %s\n", buf6);

	char buf7[50] = { '1', 'a', 'b', '\0', '7' };
	printf("buf7 = %s\n", buf7);

	//使用字符串初始化,编译器自动在后面补0,常用
	char buf8[] = "agjdslgjlsdjg";

	//'\0'后面最好不要连着数字,有可能几个数字连起来刚好是一个转义字符
	//'\ddd'八进制字义字符,'\xdd'十六进制转移字符
	// \012相当于\n
	char str[] = "\012abc";
	printf("str == %s\n", str);

	return 0;
}

5.5.3 字符串的输入输出

由于字符串采用了 ‘\0’ 标志, 字符串的输入输出将变得简单方便.

#include <stdio.h>

int main()
{
	char str[100];
   
	printf("input string1 : \n");
	scanf("%s", str);//scanf(“%s”,str)默认以空格分隔
	printf("output:%s\n", str);

	return 0;
}

5.5.4 字符串追加

#include <stdio.h>

int main()
{
	char str1[] = "abcdef";
	char str2[] = "123456";
	char dst[100];

	int i = 0;
	while (str1[i] != 0)
	{
		dst[i] = str1[i];
		i++;
	}

	int j = 0;
	while (str2[j] != 0)
	{
		dst[i + j] = str2[j];
		j++;
	}
	dst[i + j] = 0; //字符串结束符

	printf("dst = %s\n", dst);

	return 0;
}

5.5.5 字符串处理函数

  1. gets()
    #include <stdio.h>
    char *gets(char *s);
    功能:从标准输入读入字符,并保存到s指定的内存空间,直到出现换行符或读到文件结尾为止。
    参数:
    s:字符串首地址
    返回值:
    成功:读入的字符串
    失败:NULL
    注意: 由于 scanf() 和 gets() 无法知道字符串的大小,必须遇到换行符或督导文件结尾为止才接收输入,因此容易导致自负数组越界的情况.

  2. fgets()
    #include <stdio.h>
    char *fgets(char *s, int size, FILE *stream);
    功能:从stream指定的文件内读入字符,保存到s所指定的内存空间,直到出现换行字符、读到文件结尾或是已读了size - 1个字符为止,最后会自动加上字符 ‘\0’ 作为字符串结束。
    参数:
    s:字符串
    size:指定最大读取字符串的长度(size - 1)
    stream:文件指针,如果读键盘输入的字符串,固定写为stdin
    返回值:
    成功:成功读取的字符串
    读到文件尾或出错: NULL
    fgets()在读取一个用户通过键盘输入的字符串的时候,同时把用户输入的回车也做为字符串的一部分。通过scanf和gets输入一个字符串的时候,不包含结尾的“\n”,但通过fgets结尾多了“\n”。fgets()函数是安全的,不存在缓冲区溢出的问题。

  3. puts()
    #include <stdio.h>
    int puts(const char *s);
    功能:标准设备输出s字符串,在输出完成后自动输出一个’\n’。
    参数:
    s:字符串首地址
    返回值:
    成功:非负数
    失败:-1

  4. fputs()
    #include <stdio.h>
    int fputs(const char * str, FILE * stream);
    功能:将str所指定的字符串写入到stream指定的文件中, 字符串结束符 ‘\0’ 不写入文件。
    参数:
    str:字符串
    stream:文件指针,如果把字符串输出到屏幕,固定写为stdout
    返回值:
    成功:0
    失败:-1

  5. strlen()
    #include <string.h>
    size_t strlen(const char *s);
    功能:计算指定指定字符串s的长度,不包含字符串结束符‘\0’
    参数:
    s:字符串首地址
    返回值:字符串s的长度,size_t为unsigned int类型

  6. strcpy()
    #include <string.h>
    char *strcpy(char *dest, const char *src);
    功能:把src所指向的字符串复制到dest所指向的空间中,’\0’也会拷贝过去
    参数:
    dest:目的字符串首地址
    src:源字符首地址
    返回值:
    成功:返回dest字符串的首地址
    失败:NULL
    注意:如果参数 dest 所致的内存空间不够大, 可能会造成缓冲溢出的错误情况.

  7. strncpy()
    #include <string.h>
    char *strcpy(char *dest, const char *src);
    功能:把src所指向的字符串复制到dest所指向的空间中,’\0’也会拷贝过去
    参数:
    dest:目的字符串首地址
    src:源字符首地址
    返回值:
    成功:返回dest字符串的首地址
    失败:NULL
    char dest[20] ;
    char src[] = “hello world”;

    strncpy(dest, src, 5);
    printf("%s\n", dest);
    
    dest[5] = '\0';
    printf("%s\n", dest);
    
  8. strcat()
    #include <string.h>
    char *strcat(char *dest, const char *src);
    功能:将src字符串连接到dest的尾部,‘\0’也会追加过去
    参数:
    dest:目的字符串首地址
    src:源字符首地址
    返回值:
    成功:返回dest字符串的首地址
    失败:NULL

    	char str[20] = "123";
    	char *src = "hello world";
    	printf("%s\n", strcat(str, src));
    
  9. strncat()
    #include <string.h>
    char *strncat(char *dest, const char *src, size_t n);
    功能:将src字符串前n个字符连接到dest的尾部,‘\0’也会追加过去
    参数:
    dest:目的字符串首地址
    src:源字符首地址
    n:指定需要追加字符串个数
    返回值:
    成功:返回dest字符串的首地址
    失败:NULL

    char str[20] = "123";
    char *src = "hello world";
    printf("%s\n", strncat(str, src, 5));
    
  10. strcmp()
    #include <string.h>
    int strcmp(const char *s1, const char *s2);
    功能:比较 s1 和 s2 的大小,比较的是字符ASCII码大小。
    参数:
    s1:字符串1首地址
    s2:字符串2首地址
    返回值:
    相等:0
    大于:>0
    小于:<0

    char *str1 = “hello world”;
    char *str2 = “hello mike”;

       if (strcmp(str1, str2) == 0)
       {
       	printf("str1==str2\n");
       }
       else if (strcmp(str1, str2) > 0)
       {
       	printf("str1>str2\n");
       }	
       else
       {
       	printf("str1<str2\n");
       }
    
  11. strncmp()
    #include <string.h>
    int strncmp(const char *s1, const char *s2, size_t n);
    功能:比较 s1 和 s2 前n个字符的大小,比较的是字符ASCII码大小。
    参数:
    s1:字符串1首地址
    s2:字符串2首地址
    n:指定比较字符串的数量
    返回值:
    相等:0
    大于: > 0
    小于: < 0

    char *str1 = “hello world”;
    char *str2 = “hello mike”;

       if (strncmp(str1, str2, 5) == 0)
       {
       	printf("str1==str2\n");
       }
       else if (strcmp(str1, "hello world") > 0)
       {
       	printf("str1>str2\n");
       }
       else
       {
       	printf("str1<str2\n");
       }
    
  12. sprintf()
    #include <stdio.h>
    int sprintf(char *_CRT_SECURE_NO_WARNINGS, const char *format, …);
    功能:根据参数format字符串来转换并格式化数据,然后将结果输出到str指定的空间中,直到出现字符串结束符 ‘\0’ 为止。
    参数:
    str:字符串首地址
    format:字符串格式,用法和printf()一样
    返回值:
    成功:实际格式化的字符个数
    失败: - 1

    	char dst[100] = { 0 };
    	int a = 10;
    	char src[] = "hello world";
    	printf("a = %d, src = %s", a, src);
    	printf("\n");
    
    	int len = sprintf(dst, "a = %d, src = %s", a, src);
    	printf("dst = \" %s\"\n", dst);
    	printf("len = %d\n", len);
    
  13. sscanf()
    #include <stdio.h>
    int sscanf(const char *str, const char *format, …);
    功能:从str指定的字符串读取数据,并根据参数format字符串来转换并格式化数据。
    参数:
    str:指定的字符串首地址
    format:字符串格式,用法和scanf()一样
    返回值:
    成功:参数数目,成功转换的值的个数
    失败: - 1

    	char src[] = "a=10, b=20";
    	int a;
    	int b;
    	sscanf(src, "a=%d,  b=%d", &a, &b);
    	printf("a:%d, b:%d\n", a, b);
    
  14. strchr()
    #include <string.h>
    char *strchr(const char *s, int c);
    功能:在字符串s中查找字母c出现的位置
    参数:
    s:字符串首地址
    c:匹配字母(字符)
    返回值:
    成功:返回第一次出现的c地址
    失败:NULL

       char src[] = "ddda123abcd";
       char *p = strchr(src, 'a');
       printf("p = %s\n", p);
    
  15. strstr()
    #include <string.h>
    char *strstr(const char *haystack, const char *needle);
    功能:在字符串haystack中查找字符串needle出现的位置
    参数:
    haystack:源字符串首地址
    needle:匹配字符串首地址
    返回值:
    成功:返回第一次出现的needle地址
    失败:NULL

       char src[] = "ddddabcd123abcd333abcd";
       char *p = strstr(src, "abcd");
       printf("p = %s\n", p);
    
  16. strtok()
    #include <string.h>
    char *strtok(char *str, const char *delim);
    功能:来将字符串分割成一个个片段。当strtok()在参数s的字符串中发现参数delim中包含的分割字符时, 则会将该字符改为\0 字符,当连续出现多个时只替换第一个为\0。
    参数:
    str:指向欲分割的字符串
    delim:为分割字符串中包含的所有字符
    返回值:
    成功:分割后字符串首地址
    失败:NULL

- 在第一次调用时: strtok ()必须给与参数 s 字符串
- 往后调用则见参数 s 设置成 NULL , 每次调用成功则返回指向被分割出片段的指针
    char a[100] = "adc*fvcv*ebcy*hghbdfg*casdert";
    	char *s = strtok(a, "*");//将"*"分割的子串取出
    	while (s != NULL)
    	{
    		printf("%s\n", s);
    		s = strtok(NULL, "*");
    	}
  1. atoi()
    #include <stdlib.h>
    int atoi(const char *nptr);
    功能:atoi()会扫描nptr字符串,跳过前面的空格字符,直到遇到数字或正负号才开始做转换,而遇到非数字或字符串结束符(’\0’)才结束转换,并将结果返回返回值。
    参数:
    nptr:待转换的字符串
    返回值:成功转换后整数
    类似类型有:
    • atof(): 把一个小数形式的字符串转化为一个浮点数

    • atol(): 将有一个字符串转换为 long 类型
      char str1[] = “-10”;
      int num1 = atoi(str1);
      printf(“num1 = %d\n”, num1);

        char str2[] = "0.123";
        double num2 = atof(str2);
        printf("num2 = %lf\n", num2);
      
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Damon_duanlei/article/details/84995428

智能推荐

稀疏编码的数学基础与理论分析-程序员宅基地

文章浏览阅读290次,点赞8次,收藏10次。1.背景介绍稀疏编码是一种用于处理稀疏数据的编码技术,其主要应用于信息传输、存储和处理等领域。稀疏数据是指数据中大部分元素为零或近似于零的数据,例如文本、图像、音频、视频等。稀疏编码的核心思想是将稀疏数据表示为非零元素和它们对应的位置信息,从而减少存储空间和计算复杂度。稀疏编码的研究起源于1990年代,随着大数据时代的到来,稀疏编码技术的应用范围和影响力不断扩大。目前,稀疏编码已经成为计算...

EasyGBS国标流媒体服务器GB28181国标方案安装使用文档-程序员宅基地

文章浏览阅读217次。EasyGBS - GB28181 国标方案安装使用文档下载安装包下载,正式使用需商业授权, 功能一致在线演示在线API架构图EasySIPCMSSIP 中心信令服务, 单节点, 自带一个 Redis Server, 随 EasySIPCMS 自启动, 不需要手动运行EasySIPSMSSIP 流媒体服务, 根..._easygbs-windows-2.6.0-23042316使用文档

【Web】记录巅峰极客2023 BabyURL题目复现——Jackson原生链_原生jackson 反序列化链子-程序员宅基地

文章浏览阅读1.2k次,点赞27次,收藏7次。2023巅峰极客 BabyURL之前AliyunCTF Bypassit I这题考查了这样一条链子:其实就是Jackson的原生反序列化利用今天复现的这题也是大同小异,一起来整一下。_原生jackson 反序列化链子

一文搞懂SpringCloud,详解干货,做好笔记_spring cloud-程序员宅基地

文章浏览阅读734次,点赞9次,收藏7次。微服务架构简单的说就是将单体应用进一步拆分,拆分成更小的服务,每个服务都是一个可以独立运行的项目。这么多小服务,如何管理他们?(服务治理 注册中心[服务注册 发现 剔除])这么多小服务,他们之间如何通讯?这么多小服务,客户端怎么访问他们?(网关)这么多小服务,一旦出现问题了,应该如何自处理?(容错)这么多小服务,一旦出现问题了,应该如何排错?(链路追踪)对于上面的问题,是任何一个微服务设计者都不能绕过去的,因此大部分的微服务产品都针对每一个问题提供了相应的组件来解决它们。_spring cloud

Js实现图片点击切换与轮播-程序员宅基地

文章浏览阅读5.9k次,点赞6次,收藏20次。Js实现图片点击切换与轮播图片点击切换<!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title></title> <script type="text/ja..._点击图片进行轮播图切换

tensorflow-gpu版本安装教程(过程详细)_tensorflow gpu版本安装-程序员宅基地

文章浏览阅读10w+次,点赞245次,收藏1.5k次。在开始安装前,如果你的电脑装过tensorflow,请先把他们卸载干净,包括依赖的包(tensorflow-estimator、tensorboard、tensorflow、keras-applications、keras-preprocessing),不然后续安装了tensorflow-gpu可能会出现找不到cuda的问题。cuda、cudnn。..._tensorflow gpu版本安装

随便推点

物联网时代 权限滥用漏洞的攻击及防御-程序员宅基地

文章浏览阅读243次。0x00 简介权限滥用漏洞一般归类于逻辑问题,是指服务端功能开放过多或权限限制不严格,导致攻击者可以通过直接或间接调用的方式达到攻击效果。随着物联网时代的到来,这种漏洞已经屡见不鲜,各种漏洞组合利用也是千奇百怪、五花八门,这里总结漏洞是为了更好地应对和预防,如有不妥之处还请业内人士多多指教。0x01 背景2014年4月,在比特币飞涨的时代某网站曾经..._使用物联网漏洞的使用者

Visual Odometry and Depth Calculation--Epipolar Geometry--Direct Method--PnP_normalized plane coordinates-程序员宅基地

文章浏览阅读786次。A. Epipolar geometry and triangulationThe epipolar geometry mainly adopts the feature point method, such as SIFT, SURF and ORB, etc. to obtain the feature points corresponding to two frames of images. As shown in Figure 1, let the first image be ​ and th_normalized plane coordinates

开放信息抽取(OIE)系统(三)-- 第二代开放信息抽取系统(人工规则, rule-based, 先抽取关系)_语义角色增强的关系抽取-程序员宅基地

文章浏览阅读708次,点赞2次,收藏3次。开放信息抽取(OIE)系统(三)-- 第二代开放信息抽取系统(人工规则, rule-based, 先关系再实体)一.第二代开放信息抽取系统背景​ 第一代开放信息抽取系统(Open Information Extraction, OIE, learning-based, 自学习, 先抽取实体)通常抽取大量冗余信息,为了消除这些冗余信息,诞生了第二代开放信息抽取系统。二.第二代开放信息抽取系统历史第二代开放信息抽取系统着眼于解决第一代系统的三大问题: 大量非信息性提取(即省略关键信息的提取)、_语义角色增强的关系抽取

10个顶尖响应式HTML5网页_html欢迎页面-程序员宅基地

文章浏览阅读1.1w次,点赞6次,收藏51次。快速完成网页设计,10个顶尖响应式HTML5网页模板助你一臂之力为了寻找一个优质的网页模板,网页设计师和开发者往往可能会花上大半天的时间。不过幸运的是,现在的网页设计师和开发人员已经开始共享HTML5,Bootstrap和CSS3中的免费网页模板资源。鉴于网站模板的灵活性和强大的功能,现在广大设计师和开发者对html5网站的实际需求日益增长。为了造福大众,Mockplus的小伙伴整理了2018年最..._html欢迎页面

计算机二级 考试科目,2018全国计算机等级考试调整,一、二级都增加了考试科目...-程序员宅基地

文章浏览阅读282次。原标题:2018全国计算机等级考试调整,一、二级都增加了考试科目全国计算机等级考试将于9月15-17日举行。在备考的最后冲刺阶段,小编为大家整理了今年新公布的全国计算机等级考试调整方案,希望对备考的小伙伴有所帮助,快随小编往下看吧!从2018年3月开始,全国计算机等级考试实施2018版考试大纲,并按新体系开考各个考试级别。具体调整内容如下:一、考试级别及科目1.一级新增“网络安全素质教育”科目(代..._计算机二级增报科目什么意思

conan简单使用_apt install conan-程序员宅基地

文章浏览阅读240次。conan简单使用。_apt install conan