1 c++编程基础

重新系统学习c++语言,并将学习过程中的知识在这里抄录、总结、沉淀。同时希望对刷到的朋友有所帮助,一起加油哦!

生命就像一朵花,要拼尽全力绽放!死磕自个儿,身心愉悦!

 

系列文章列表:

1 c++编程-基础

2 c++编程-核心

1 c++揭开面纱

1.1 编程工具

        注:开发环境指在windows机器。

        实际项目开发中开发工具可选择:

        (1) Visual Studio--可直接创建项目,并编译运行,较方便简单。

        (2) vscode--可写代码,但对于Windows系统而言就需要安装Mingw-w64来获得编译器。(网上可搜索到安装配置方法不再累述) 

        (3) https://lightly.teamcode.com/  初学者推荐这个站点,可以在线建项目,并运行出结果。方便快捷。

提示:本文采用 lightly 站点编程。

1.2 第一个c++小程序                

#include<iostream>
using namespace std;

int main() {

	cout << "Hello world" << endl;


	return 0;
}

运行后输出:

        

1.3 注释

作用:在代码中加一些说明和解释,方便自己或其他程序员程序员阅读代码。

格式:

     1. 单行注释

         通常放在一行代码的上方,或者一条语句的末尾,对该行代码说明。

   语法: // 注释信息

     2. 多行注释: 

        通常放在一段代码的上方,对该段代码做整体说明。

        语法: /* 注释信息 */

         提示:编译器在编译代码时,会忽略注释的内容

#include<iostream>
using namespace std;

int main() {

	// 这是单行注释

    /*
    这是多行注释
    这是多行注释
    */
	
	system("pause");

	return 0;
}

1.4 变量

作用:给一段指定的内存空间起名,方便操作这段内存

语法数据类型 变量名 = 初始值;

示例:int a = 1;

注意:C++在创建变量时,必须给变量一个初始值,否则会报错

1.5 常量

作用:用于记录程序中不可更改的数据

定义常量两种方式:

        1. #define 宏常量: 

                通常在文件上方定义,表示一个常量

               语法:#define 常量名 常量值

        2. const修饰的变量 

                通常在变量定义前加关键字const,修饰该变量为常量,不可修改

                语法:const 数据类型 常量名 = 常量值

示例:

#include<iostream>
using namespace std;

//1、宏常量
#define day 7

int main() {

	cout << "一周里总共有 " << day << " 天" << endl;
	//day = 8;  //报错,宏常量不可以修改

	//2、const修饰变量
	const int month = 12;
	cout << "一年里总共有 " << month << " 个月份" << endl;
	//month = 24; //报错,常量是不可以修改的
	
	
	system("pause");

	return 0;
}

运行后输出:

        

1.6 关键字

作用:关键字是C++中预先保留的单词(标识符)

  • 在定义变量或者常量时候,不要用关键字

C++关键字如下:

asmelsenewthis
autoenumoperatorthrow
boolexplicitprivatetrue
breakexportprotectedtry
caseexternpublictypedef
catchfalseregistertypeid
charfloatreinterpret_casttypename
classforreturnunion
constfriendshortunsigned
const_castgotosignedusing
continueifsizeofvirtual
defaultinlinestaticvoid
deleteintstatic_castvolatile
dolongstructwchar_t
doublemutableswitchwhile
dynamic_castnamespacetemplate

完整关键字介绍可查阅:

C++ 的关键字(保留字)完整介绍 | 菜鸟教程

提示:在给变量或者常量起名称时候,不要用C++得关键字,否则会产生歧义。

1.7 标识符命名规则

作用:C++规定给标识符(变量、常量)命名时,有一套自己的规则

  • 标识符只能由字母、数字、下划线组成
  • 第一个字符必须为字母或下划线
  • 标识符中字母区分大小写
  • 标识符不能是关键字

建议:给标识符命名时,争取做到见名知意的效果,方便自己和他人的阅读。

2 数据类型

C++规定在创建一个变量或者常量时,必须要指定出相应的数据类型,否则无法给变量分配内存

2.1 总括

基本的内置类型

c++定义的基本数据类型包括两种:

        算术类型:包含整型、浮点型、字符型、布尔型

        空类型(void)

其中,算术类型也可以按另一种方式来分类包含两种:

        整型。包括字符和布尔类型在内。

        浮点型

C++ 为程序员提供了种类丰富的内置数据类型和用户自定义的数据类型。下表列出了实际使用时七种基本的算术数据类型:

类型关键字备注
整型int
浮点型float
双浮点型double
布尔型bool

有两个值:

true 真,本质是1

false 假,本质是0

字符型char

定义: char ch = 'a';

只能用单引号,且里面只能有一个字符,不能多个。

字符型变量并不是把字符本身放到内存中存储,而是将对应的ASCII编码放入到存储单元。要记住两个字符的ASCII编码:a--97,A--65,其他顺序推算。

无类型void
宽字符型

wchar_t

真实定义:

typedef short int wchar_t;
所以wchar_t 实际上的空间是和 short int 一样

一些基本类型可以使用一个或多个类型修饰符进行修饰:

  • signed
  • unsigned
  • short
  • long

下表显示了各种变量类型在内存中存储值时需要占用的内存,以及该类型的变量所能存储的最大值和最小值。

注意:不同系统会有所差异,一字节为 8 位。

注意:默认情况下,int、short、long都是带符号的,即 signed。

注意:long int 8 个字节,int 都是 4 个字节,早期的 C 编译器定义了 long int 占用 4 个字节,int 占用 2 个字节,新版的 C/C++ 标准兼容了早期的这一设定。

类型范围
char1 个字节-128 到 127 或者 0 到 255
unsigned char1 个字节0 到 255
signed char1 个字节-128 到 127
int4 个字节-2147483648 到 2147483647
unsigned int4 个字节0 到 4294967295
signed int4 个字节-2147483648 到 2147483647
short int2 个字节-32768 到 32767
unsigned short int2 个字节0 到 65,535
signed short int2 个字节-32768 到 32767
long int8 个字节-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807
signed long int8 个字节-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807
unsigned long int8 个字节0 到 18,446,744,073,709,551,615
float4 个字节精度型占4个字节(32位)内存空间,+/- 3.4e +/- 38 (~7 个数字)
double8 个字节双精度型占8 个字节(64位)内存空间,+/- 1.7e +/- 308 (~15 个数字)
long double16 个字节长双精度型 16 个字节(128位)内存空间,可提供18-19位有效数字。
wchar_t2 或 4 个字节1 个宽字符

2.2 sizeof

各数据类型所占内存空间不同,可能我们没那么好记忆来记住它们,c++提供了sizeof关键字来解决这个问题。

作用:利用sizeof关键字可以统计数据类型所占内存大小占用几个字节

语法: sizeof( 数据类型 或 变量)

示例:

#include <iostream>
using namespace std;

int main() {
    int a = 1;
    
    cout << "short 类型所占内存空间为: " << sizeof(short) << endl;

    cout << "int 类型所占内存空间为: " << sizeof(int) << endl;

    cout << "用变量a获取 int 类型所占内存空间为: " << sizeof(a) << endl;

    cout << "long 类型所占内存空间为: " << sizeof(long) << endl;

    cout << "long long 类型所占内存空间为: " << sizeof(long long) << endl;

    system("pause");

    return 0;
}

 运行后输出:

        

2.3 字符串

作用:用于表示一串字符

两种风格:

        1. C风格字符串

        char 变量名[] = "字符串值"

        注意:C风格的字符串要用双引号括起来

       2.  C++风格字符串: 

  string 变量名 = "字符串值"

        注意:C++风格字符串,需要加入头文件 #include <string>

示例:

#include <iostream>
#include <string>
using namespace std;

int main() {
    char str1[] = "abc";
    cout << "str1字符串为:" << str1 << endl;

    string str2 = "123";
    cout << "str2字符串为:" << str2 << endl;

    return 0;
}

运行后输出:

        

2.4 数据的输入

作用:用于从键盘获取数据

关键字:cin

语法: cin >> 变量

示例:

#include <iostream>
using namespace std;

int main() {
    int a = 0;
    cout << "请给a赋值:" << endl;
    cin >> a;
    cout << "a的值为:" << a << endl;

    return 0;
}

 运行后输出:

        

2.4.2 istream对象作为条件

问题:当istream对象作为条件时,怎么判断条件是成功、失败呢?

本质:检测的是流的状态。

成功true:

        流是有效的,即未遇到错误。

失败false:

        遇到文件结束符

        或遇到无效舒服(例如读入的值要求是整型,确输入的不是)

从键盘输入文件结束符:

        windows系统中-------------------为:ctrl+z,然后按enter或return键

        在unix/mac os x系统中-------------------为:ctrl+D

示例:

#include <iostream>
#include <string>

using namespace std;

void test() {
	int sum = 0;
	int value = 0;
	// istream对象作为条件
	// 如果遇到文件结束符,或遇到无效输入时,才会条件结果为false
	//windows系统中,文件结束符为:ctrl+z,然后按enter或return键
	// 在unix/mac os x系统中,文件结束符为:ctrl+D
	while (cin >> value) {
		sum += value;
	}
	cout << " sum = " << sum << endl;
}

int main() {
	test();

	system("pause");
	return 0;
}

3 运算符

作用:用于执行代码的运算

本章主要讲解以下几类运算符:

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

3.1 算术运算符

作用:用于处理四则运算

算术运算符包括以下符号:

运算符术语示例结果
+正号+33
-负号-3-3
+10 + 515
-10 - 55
*10 * 550
/10 / 52
%取模(取余)10 % 31
++前置递增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;

注意:

  • 在除法运算中,除数不能为0
  • 在取模运算中,除数不能为0。只有整型变量可以进行取模运算,不能是浮点型变量。
  • 整数进行除法运算,若除不尽,则结果只有整数部分,小数部分不保留。

3.2 赋值运算符

作用:用于将表达式赋值给变量

赋值运算符包括以下符号:

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

3.3 比较运算符

作用:用于表达式间的比较,并返回一个真值或假值

比较运算符包括以下符号:

运算符术语示例

结果

(1为真,0为假)

==等于1==20
!=不等于1!=21
<小于1<21
>大于1>20
<=小于等于1<=21
>=大于等于1>=20

3.4 逻辑运算符

作用:用于表达式间的比较逻辑运算,并返回一个真值或假值

逻辑运算符包括以下符号:

运算符术语示例

结果

(1为真,0为假)

!!a若a为真,则结果为假;若a为假,则结果为真;
&&a && b若a和b都为真,则结果为真,否则结果为假
||a || b若a和b有一个为真,则结果为真;只有二者都为假时,结果为假

总结规律:

非:真变假,假变真;

与:全真为真,其余为假;

或:全假为假,其余为真。

3.5 逗号运算符

作用:用于表达式的分隔。如果一个语句用多个分隔符分开多个表达式,通常返回最后一个表达式的值。

示例:

#include <iostream>
using namespace std;

int main() {
    int n = ( 3,4,5);
    cout << "n=" << n << endl;

    return 0;
}

输出结果:

n=5

3.6 条件运算符

三目运算符,又称三元运算符,或条件运算符。

格式:表达式1?表达式2:表达式3;

作用:根据表达式1的真假,返回结果。若表达式1为真,则返回表达式2的结果;若表达式1为假,则返回表达式3的结果。

示例:

#include <iostream>
using namespace std;

int main() {
    int a,b,c;
    a=7;
    b=6;
    //若a>b为真,c=a;若a>b为假,c=b;
    c=(a>b)?a:b;
    cout << "c=" << c << endl;

    return 0;
}

结果:

c=7

3.8 运算符优先级

作用:当多种运算符出现时,按怎样的运算次序。

(以下内容抄录自其他c++学习文档)

C语言运算符优先级

优先级

运算符

名称或含义

使用形式

结合方向

说明

1

[]

数组下标

数组名[常量表达式]

左到右

--

()

圆括号

(表达式)/函数名(形参表)

--

.

成员选择(对象)

对象.成员名

--

->

成员选择(指针)

对象指针->成员名

--

2

-

负号运算符

-表达式

右到左

单目运算符

~

按位取反运算符

~表达式

++

自增运算符

++变量名/变量名++

--

自减运算符

--变量名/变量名--

*

取值运算符

*指针变量

&

取地址运算符

&变量名

!

逻辑非运算符

!表达式

(类型)

强制类型转换

(数据类型)表达式

--

sizeof

长度运算符

sizeof(表达式)

--

3

/

表达式/表达式

左到右

双目运算符

*

表达式*表达式

%

余数(取模)

整型表达式%整型表达式

4

+

表达式+表达式

左到右

双目运算符

-

表达式-表达式

5

<< 

左移

变量<<表达式

左到右

双目运算符

>> 

右移

变量>>表达式

6

大于

表达式>表达式

左到右

双目运算符

>=

大于等于

表达式>=表达式

小于

表达式<表达式

<=

小于等于

表达式<=表达式

7

==

等于

表达式==表达式

左到右

双目运算符

!=

不等于

表达式!= 表达式

8

&

按位与

表达式&表达式

左到右

双目运算符

9

^

按位异或

表达式^表达式

左到右

双目运算符

10

|

按位或

表达式|表达式

左到右

双目运算符

11

&&

逻辑与

表达式&&表达式

左到右

双目运算符

12

||

逻辑或

表达式||表达式

左到右

双目运算符

13

?:

条件运算符

表达式1?

表达式2: 表达式3

右到左

三目运算符

14

=

赋值运算符

变量=表达式

右到左

--

/=

除后赋值

变量/=表达式

--

*=

乘后赋值

变量*=表达式

--

%=

取模后赋值

变量%=表达式

--

+=

加后赋值

变量+=表达式

--

-=

减后赋值

变量-=表达式

--

<<=

左移后赋值

变量<<=表达式

--

>>=

右移后赋值

变量>>=表达式

--

&=

按位与后赋值

变量&=表达式

--

^=

按位异或后赋值

变量^=表达式

--

|=

按位或后赋值

变量|=表达式

--

15

逗号运算符

表达式,表达式,…

左到右

--

说明:

    同一优先级的运算符,运算次序由结合方向所决定。
    简单记就是:! > 算术运算符 > 关系运算符 > && > || > 赋值运算符

4 语句与程序流结构

C/C++支持最基本的三种程序运行结构:

  •  顺序结构:程序按代码顺序执行
  •  选择结构:依据条件是否满足,有选择的执行相应代码块
  • 循环结构:依据条件是否满足,多次循环执行某段代码

4.1 语句分类

4.2 选择结构

4.2.1 if语句

(1)单行if语句

        格式:

        if(条件1) 

        {

                条件1为真时,要执行的代码

        }

#include <iostream>
using namespace std;

int main() {
    int score=0;
    cout << "请输入你的分数:";
    cin>> score;
    
    if(score>600)
    {
        cout << "恭喜你考上一本" << endl;
    }
   
    return 0;
}

输出:

        a大于b

(2)多行if语句

        格式:

        if(条件1)

        {

                条件1为真时,要执行的代码

        }

        else{

                条件1为假时,要执行的代码

        }

示例:

#include <iostream>
using namespace std;

int main() {
    int score=0;
    cout << "请输入你的分数:";
    cin>> score;
    
    if(score>600)
    {
        cout << "恭喜你考上一本" << endl;
    }
    else{
        cout << "未考上一本" << endl;
    }

    return 0;
}

(3)多条件if语句

        格式:

         if(条件1)

        {

                条件1为真时,要执行的代码

        }

        else if(条件2){

                条件2为真时,要执行的代码

        }

        ……

        else {        

                所有条件都不满足时,要执行的代码

        }

示例:

#include <iostream>
using namespace std;

int main() {
    int score=0;
    cout << "请输入你的分数:";
    cin>> score;
    
    if(score>600)
    {
        cout << "恭喜你考上一本" << endl;
    }
    else if(score>500){
        cout << "恭喜你考上二本" << endl;
    }
    else if(score>400){
        cout << "恭喜你考上三本" << endl;
    }
    else {
        cout << "未考上本科" << endl;
    }

    return 0;
}

4.2.2 switch语句

作用:根据表达式结果,执行多种选择条件的结果。

格式:

switch(表达式)

{

        case 结果1: 执行语句;break;

        case 结果2: 执行语句;break;

        ……

        default: 执行语句;break;

}

示例:

#include <iostream>
using namespace std;

int main() {

	//请给电影评分 
	//10 ~ 9   经典   
	// 8 ~ 7   非常好
	// 6 ~ 5   一般
	// 5分以下 烂片

	int score = 0;
	cout << "请给电影打分" << endl;
	cin >> score;

	switch (score)
	{
	case 10:
	case 9:
		cout << "经典" << endl;
		break;
	case 8:
		cout << "非常好" << endl;
		break;
	case 7:
	case 6:
		cout << "一般" << endl;
		break;
	default:
		cout << "烂片" << endl;
		break;
	}

	system("pause");

	return 0;
}

注意:

1、switch的判断表达式类型只能是整型或字符类。不可以是一个区间。

2、case里如果没有break会一直往下执行后面的语句。

总结:

与if语句相比,对于多条件判断时,switch的优点是结构清晰,执行效率高;缺点是不可以判断区间。

4.3 循环结构

循环结构,指的是在满足条件下,重复执行某段代码语句。

4.3.1 while语句

作用:满足循环条件时,执行循环语句。

格式:

while(循环条件){

        循环语句

}

示例:

#include <iostream>
using namespace std;

int main() {
    //案例:输出1到9个数字
	int a = 1;
    while(a < 10){
        cout << a << endl;
        a++;
    }

	system("pause");

	return 0;
}

注意:

       程序必须有不满足循环条件的时候,以便跳出循环,防止出现死循环的情况。

4.3.2 do while语句

作用:满足循环条件时,执行循环语句。

格式:

        do{
                循环语句

        }while(循环条件)

示例:

#include <iostream>
using namespace std;

int main() {
    //案例:输出1到9个数字
	int a = 1;
    do{
        cout << a << endl;
        a++;
    } while(a < 10)

	system("pause");

	return 0;
}

总结:

    do while与while的区别在于,do while一定会执行一遍循环语句,再判断是否满足循环条件。

4.3.3 for语句

作用:满足循环条件时,执行循环语句。

格式:

        for(起始循环条件;条件表达式;末尾循环体)

        {
                循环语句

        }

示例:

#include <iostream>
using namespace std;

int main() {
    // 打印 0到9的数字
    for(int a = 0; a < 10; a++)
    {
        cout << a << endl;
    }
	system("pause");

	return 0;
}

4.4 跳转语句

4.4.1 break

作用:跳出选择结构或循环结构

使用时机:

  • 出现在switch条件语句中,用于终止case并跳出switch;
  • 出现在循环结构中,用于跳出当前循环结构;
  • 出现在嵌套循环结构中,跳出最近的内层循环。

4.4.2 continue

作用:跳过本次循环中余下未执行的语句,继续执行下一次循环。

示例:

#include <iostream>
using namespace std;

int main() {
    // 打印 0到10以内的奇数
    for(int a = 0; a <= 10; a++)
    {
        if(a % 2 == 0 )
        {
            continue;
        }
        cout << a << endl;
    }
	system("pause");

	return 0;
}

输出:

1

3

5

7

9

4.4.3 goto

作用:无条件跳转到目的语句。

通常是打一个标记,然后执行goto语句,跳转到标记的位置。

示例:

#include <iostream>
using namespace std;

int main() {
    cout << "1" << endl;
    cout << "2" << endl;
    
    goto FLAG; // 跳转到FLAG标记处

    cout << "3" << endl;

    FLAG: //标记

    cout << "4" << endl;
	system("pause");

	return 0;
}

结果:

1

2

4

注意:

     goto比较影响程序的可读性,不推荐使用。

5 数组

由相同的数据组成的一个集合,叫数组。

特点:

  • 数组中的每个元素都是相同的数据类型;
  • 数组中数据在内存中是连续存储的;

5.1 一维数组

5.1.1定义

有三种定义方式及特点:

(1) 数据类型  数组名[ 数组长度 ]; 

  • 数组长度固定
  • 需要给元素赋值,若未赋值,则元素值不一定为0,可能是个不确定值,使用时需要注意,防止错误。

(2) 数据类型  数组名[ 数组长度 ] = { 值1,值2 ...};

  • 数组长度固定
  • 元素值{}中已给定,若缺少,则用0补全;

(3) 数据类型  数组名[ ] = { 值1,值2 ...};

  • 数组长度根据{}中元素个数来确定,是个固定长度;
  • 元素值{}中已给定;
#include <iostream>
using namespace std;

int main() {
    //定义方式1:数据类型 数组名[元素个数]
    // 若未给元素赋值,则元素的值是个不确定数。
    int arr1[10];
    arr1[0] = 10;
    arr1[1] = 20;
    
    cout << "打印arr1" << endl;
    for (int i = 0; i <= 9; i++) {
        cout << arr1[i] << endl;
    }

    //  定义方式2:数据类型 数组名[元素个数] = {值1,值2,……}
    // 如果{}中元素个数不足10个,则剩余元素值用0补全
    cout << "打印arr2" << endl;
    int arr2[10] = {1, 2, 3, 4, 5};
    for (int i = 0; i <= 19; i++) {
        cout << arr2[i] << endl;
    }

    //  定义方式2:数据类型 数组名[元素个数] = {值1,值2,……}
    cout << "打印arr3" << endl;
    int arr3[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
    for (int i = 0; i <= 9; i++) {
        cout << arr3[i] << endl;
    }


    //使用超出数组下标元素时,不会报错,但是值有问题
    for (int i = 20; i <= 30; i++) {
           cout<<"超出数组下标的错误元素值"<<arr3[i]<<endl;

    }
    system("pause");

    return 0;
}

结果:

打印arr1
10
20
0
0
4199536
0
4198688
0
816941264
32767
打印arr2
1
2
3
4
5
0
0
0
0
0
4199605
10
10
20
0
0
4199536
0
4198688
0
打印arr3
10
20
30
40
50
60
70
80
90
100
超出数组下标的错误元素值0
超出数组下标的错误元素值0
超出数组下标的错误元素值4199605
超出数组下标的错误元素值10
超出数组下标的错误元素值10
超出数组下标的错误元素值20
超出数组下标的错误元素值0
超出数组下标的错误元素值0
超出数组下标的错误元素值4199536
超出数组下标的错误元素值0
超出数组下标的错误元素值4198688

总结:

  1. 定义数组名不要和其他变量重名;
  2. 数组下标是从0开始的;
  3. 注意不要使用未赋值元素,可能是不确定的值。

5.1.2 数组名

用途:

1. 可以通过数组名统计整个数组占用内存大小;  sizeof(数组名)

2. 可以通过数组名查看数组首地址; sizeof(数组名[0])  或sizeof(数组名)

示例:

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

int main() {
    //  1. 可以通过数组名统计整个数组占用内存大小;
    int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    cout << "整个数组占用内存空间为:" << sizeof(arr) << endl;
    cout << "每个元素占用内存空间为:" << sizeof(arr[0]) << endl;
    cout << "数组元素个数为:" << sizeof(arr) / sizeof(arr[0]) << endl;

    //  2. 可以通过数组名查看数组首地址;
    printf("数组首地址为:%d\n",arr);
    printf("第一个元素首地址为:%d\n",&arr[0]);
    printf("第二个元素首地址为:%d\n",&arr[1]);
    system("pause");

    return 0;
}

结果:

整个数组占用内存空间为:40
每个元素占用内存空间为:4
数组元素个数为:10
数组首地址为:922989696
第一个元素首地址为:922989696
第二个元素首地址为:922989700

总结:

  1. 数组名是常量不可以赋值;
  2. 直接打印数组名,可以查看数组的首地址;
  3. sizeof(数组名)可获取数组所占内存大小;

5.1.3 元素逆置

需求:声明一个6个元素的数组,并且将元素逆置.

(如原数组元素为:1,3,2,5,4,6;逆置后输出结果为:6,4,5,2,3,1);
代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

int main() {
    //  1、创建数组
    int arr[6] = {1, 3, 2, 5, 4, 6};
    for (int i = 0; i < 6; i++) {
        cout << arr[i] << endl;
    }

    //  2、实现逆置
    //  2.1 记录起始下标
    //  2.2 记录结束下标
    //  2.3 互换起始下标和结束下标元素
    //  2.4 起始下标++  结束下标--
    //  2.5 循环执行2.1至2.4步骤,直至起始下标 >= 结束下标
    int start = 0;                              //起始坐标
    int end = sizeof(arr) / sizeof(arr[0]) - 1; //结束坐标
    while (start < end) {
        //实现元素互换
        int tmp = arr[start];
        arr[start] = arr[end];
        arr[end] = tmp;

        // 下标更新
        start++;
        end--;
    }

    //  3、打印逆置后的数组
    cout << "逆置后的数组:" << endl;
    for (int i = 0; i < 6; i++) {
        cout << arr[i] << endl;
    }

    system("pause");

    return 0;
}

5.1.4 冒泡排序

#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;

int main() {
    // 冒泡排序 将数组按升序排序
    // 1 比较相邻的元素,如果第一个比第二个大,就交换;
    // 2 对每一个相邻的元素做同样的操作,执行完毕后,找到最大值;
    // 3 重复以上两个步骤,每次比较次数减1,直到不需要比较
    // 思考方法:可通过画图找到排序轮次,每轮比对次数的规律。
    // 排序总轮数 = 元素个数 -1
    // 每轮比对次数 = 元素个数 - 排序轮数 - 1

    int arr[10] = {5, 2, 8, 4, 3, 7, 9, 1, 0, 6};
    int len = sizeof(arr) / sizeof(arr[0]);

    for (int i = 0; i < len; i++) {
        cout << arr[i];
    }
    cout << endl;

    for (int i = 0; i < len - 1; i++) {
        for (int j = 0; j < len - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                int tmp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = tmp;
            }
        }
    }

    for (int i = 0; i < len; i++) {
        cout << arr[i];
    }
    cout << endl;

    system("pause");
    return 0;
}

5.2 二维数组

二维数组相对一维数组,多一个纬度。

5.2.1定义

有四种定义方法:

1 数据类型 数组名[行数][列数]; 

2 数据类型 数组名[行数][列数] = {{数据1,数据2}, {数据3,数据4}};

3 数据类型 数组名[行数][列数] = {数据1,数据2,数据3,数据4}; 

       特点: 根据行数及列数推导出每个元素的位置。

4 数据类型 数组名[][列数] = {数据1,数据2数据3,数据4};

        特点:根据{}中元素个数及列数可推导出行数,及每个元素的位置。

总结:

推荐使用定义2,清晰明了。

定义二维数组要给定行数列数,在定义时初始化了数据的情况下可以省略行数

示例:

#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;

int main() {

    //     1 数据类型 数组名[行数][列数]; 
    int arr1[2][3];
    arr1[0][0] = 1;
    arr1[0][1] = 2;
    arr1[0][2] = 3;
    arr1[1][0] = 4;
    arr1[1][1] = 5;
    arr1[1][2] = 6;
    cout << "arr1:" << endl;
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++) {
            cout << arr1[i][j];
        }
        cout << endl;
    }

    //     2 数据类型 数组名[行数][列数] = {{数据1,数据2}, {数据3,数据4}};
    int arr2[2][3] = {{1, 2, 3}, {4, 5, 6}};
    cout << "arr2:" << endl;
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++) {
            cout << arr2[i][j];
        }
        cout << endl;
    }

    //     3 数据类型 数组名[行数][列数] = {数据1,数据2,数据3,数据4}; 
    //       特点: 根据行数及列数推导出每个元素的位置。
    int arr3[2][3] = {1, 2, 3, 4, 5, 6};
    cout << "arr3:" << endl;
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++) {
            cout << arr3[i][j];
        }
        cout << endl;
    }

    //     4 数据类型 数组名[][列数] = {数据1,数据2数据3,数据4};
    //      特点:根据{}中元素个数及列数可推导出行数,及每个元素的位置。
    int arr4[][3] = {1, 2, 3,
                     4, 5, 6}; // 若初始化成{{1, 2, 3}, {4, 5, 6}};也可以
    cout << "arr4:" << endl;
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++) {
            cout << arr4[i][j];
        }
        cout << endl;
    }

    system("pause");
    return 0;
}

5.2.2 数组名

用途:

  1. 查看占用内存空间大小
  2. 查看二维数组的首地址
#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;

int main() {
    // 查看占用内存空间大小
    int arr[2][3] = {{1, 2, 3}, {4, 5, 6}};
    cout << "二维数组占用内存空间:" << sizeof(arr) << endl;
    cout << "二维数组第一行占用内存空间:" << sizeof(arr[0]) << endl;
    cout << "二维数组第一个元素占用内存空间:" << sizeof(arr[0][0]) << endl;
    cout << "二维数组行数:" << sizeof(arr) / sizeof(arr[0]) << endl;
    cout << "二维数组列数:" << sizeof(arr[0]) / sizeof(arr[0][0]) << endl;

    // 查看二维数组的首地址
    printf("二维数组的首地址:%d\n", arr);
    printf("二维数组第一行数据首地址:%d\n", arr[0]);
    printf("二维数组第二行数据首地址:%d\n", arr[1]);

    printf("二维数组第一个元素首地址:%d\n", &arr[0][0]);
    printf("二维数组第二个元素首地址:%d\n", &arr[0][1]);

    system("pause");
    return 0;
}

注意:

查看具体元素的地址,需要在元素前加&。例如: &arr[0][0]

6 函数

6.1 概述

作用:将经常使用的代码提炼封装起来,减少重复代码
一个较大的程序,一般分为若干个程序块,每个模块实现特定的功能。

 6.2 函数的定义

函数的定义一般主要有5个步骤:

语法

返回值类型 函数名 (参数列表)
{

         函数体语句

        return表达式

}

  • 返回值类型 :一个函数可以返回一个值。在函数定义中
  • 函数名:给函数起个名称
  • 参数列表:使用该函数时,传入的数据
  • 函数体语句:花括号内的代码,函数内需要执行的语句
  • return表达式: 和返回值类型挂钩,函数执行完后,返回相应的数据

示例:

//函数定义
int add(int num1, int num2)
{
    int sum = num1 + num2;
    return sum;
}

6.3 函数的调用

用途:使用定义好的函数

语法:函数名(参数)

示例:

#include <iostream>
#include <stdio.h>

using namespace std;

//函数定义
int add(int num1, int num2) //定义中的num1,num2称为形式参数,简称形参
{
    int sum = num1 + num2;
    return sum;
}


int main() {
    int a = 10;
    int b = 10;
    //调用add函数
    int sum = add(a, b);//调用时的a,b称为实际参数,简称实参
    cout << "sum = " << sum << endl;

    a = 100;
    b = 100;
    sum = add(a, b);
    cout << "sum = " << sum << endl;

    system("pause");
    return 0;

}

 总结:函数定义里小括号内称为形参,函数调用时传入的参数称为实参

 6.4 值传递

 所谓值传递,就是函数调用时实参将数值传入给形参

 值传递时,如果形参发生,并不会影响实参

示例:

#include <iostream>
#include <stdio.h>

using namespace std;

void swap(int num1, int num2)
{
    cout << "交换前:" << endl;
    cout << "num1 = " << num1 << endl;
    cout << "num2 = " << num2 << endl;

    int temp = num1;
    num1 = num2;
    num2 = temp;

    cout << "交换后:" << endl;
    cout << "num1 = " << num1 << endl;
    cout << "num2 = " << num2 << endl;

    //return ; 当函数声明时候,不需要返回值,可以不写return
}


int main() {
    int a = 10;
    int b = 20;
    swap(a, b);

    cout << "mian中的 a = " << a << endl;
    cout << "mian中的 b = " << b << endl;

    system("pause");

    return 0;

}

 总结: 值传递时,形参是修饰不了实参的

 6.5 函数的常见样式

常见的函数样式有4种:

  1. 1. 无参无返
  2. 2. 有参无返
  3. 3. 无参有返
  4. 4. 有参有返

示例:

//函数常见样式
//1、 无参无返
void test01()
{
    //void a = 10; //无类型不可以创建变量,原因无法分配内存
    cout << "this is test01" << endl;
    //test01(); 函数调用
}

//2、 有参无返
void test02(int a)
{
    cout << "this is test02" << endl;
    cout << "a = " << a << endl;
}

//3、无参有返
int test03()
{
    cout << "this is test03 " << endl;
    return 10;
}

//4、有参有返
int test04(int a, int b)
{
    cout << "this is test04 " << endl;
    int sum = a + b;
    return sum;
}

 6.6 函数的声明

作用: 告诉编译器函数名称及如何调用函数。函数的实际主体可以单独定义。

      函数的声明可以多次,但是函数的定义只能有一次

示例:

#include <iostream>
#include <stdio.h>

using namespace std;

//声明可以多次,定义只能一次
//声明
int max(int a, int b);
int max(int a, int b);

//定义
int max(int a, int b)
{
    return a > b ? a : b;
}

int main() {
    int a = 100;
    int b = 200;
    cout << max(a, b) << endl;

    system("pause");
    return 0;
}

6.7 函数的分文件编写

作用:将函数声明和函数定义主体分开成两个文件保存,让代码结构更加清晰

函数分文件编写一般有4个步骤:

  1. 1. 创建后缀名为.h的头文件 
  2. 2. 创建后缀名为.cpp的源文件
  3. 3. 在头文件中写函数的声明
  4. 4. 在源文件中写函数的定义

示例:

三个文件的代码分别如下:


//swap.h文件
#include<iostream>
using namespace std;

//实现两个数字交换的函数声明
void swap(int a, int b);


//swap.cpp文件
#include "swap.h"

void swap(int a, int b)
{
	int temp = a;
	a = b;
	b = temp;

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
}



//main函数文件
#include "swap.h"
int main() {
	int a = 100;
	int b = 200;
	swap(a, b);

	system("pause");
	return 0;
}

总结:

在调用函数的文件中,需要引用函数头文件:   #include "函数文件名.h"

7 指针

7.1 指针基本概念

作用:通过指针来访问内存空间。

  • 内存编号从0开始记录,一般是用十六进制数字来表示;
  • 可以利用指针来保存地址;

7.2 指针变量的定义和使用

定义语法:

数据类型 * 变量名;

示例:

#include <iostream>
using namespace std;

int main()
{
  // 1 指针定义
	int a = 10;
	// 定义指针
	int* p;
	// 让指针指向a的地址
	p = &a;
	cout << "a的地址:"<<&a<<endl;
	cout << "指针p的值:" << p << endl;

	// 2 指针使用
	*p = 2000;
	cout << "a = " << a << endl;
	cout << "*p = " << *p << endl;

    system("pause");
	return 0;
}

7.3 指针的内存空间

所有数据类型指针:

  • 在32位操作系统下,指针占用4字节内存空间(x86)
  • 在64位操作系统下,指针占用8字节内存空间(x64)

示例:

#include <iostream>
using namespace std;

int main()
{
	int a = 10;
	int* p = &a;
	cout << "int*占用内存大小:" << sizeof(p) << endl;
	cout << "long*占用内存大小:" << sizeof(long *) << endl;
	cout << "char *占用内存大小:" << sizeof(char *) << endl;
	cout << "double *占用内存大小:" << sizeof(double*) << endl;

	system("pause");
	return 0;
}

7.4 空指针和野指针

1  空指针

空指针定义:指针变量指向内存编号为0的空间;

用途:一般在初始化指针变量时,先定义指针为空指针。

语法:数据类型 * 指针名 = NULL; 

                例:int * p = NULL;

注意:空指针指向的内存是不可以访问的。换句话说在空指针未重新指向其他内存空间时不可以使用。内存编号为0至255的空间为系统占用内存,都不运行用户访问使用。

示例:

#include <iostream>
using namespace std;

int main()
{
	// 指针变量p指向内存地址编号0的空间
	int* p = NULL;

	// 访问空指针会报错
	// 内存编号0至255为系统占用编号的空间,不运行用户访问
	//cout << *p << endl;

	//可将指针重新指向其他内存空间再访问
	int a = 10;
	p = &a;
	cout << *p<< endl;

	system("pause");
	return 0;
}

2 野指针

野指针:指针变量指向非法的内存空间;

#include <iostream>
using namespace std;

int main()
{
	// 野指针,指向的内存地址并不是自己申请过的,属于指向非法内存空间
	int* p = (int *)0x112;

	// 访问会报错
	cout << *p<< endl;

	system("pause");
	return 0;
}

7.5 const修饰指针

三种情况:

1、const修饰指针--常量指针

        特点:指针指向可以修改,指针指向的值不可以修改

2、const修饰常量--指针常量

        特点:指针指向不可以修改,指针指向的值可以修改

3、const既修饰指针,也修饰常量

        特点:指针指向不可以修改,指针指向的值也不可以修改

看const右侧紧跟的是指针还是变量名,是指针就是常量指针,是变量名就是指针常量。

示例:

#include <iostream>
using namespace std;

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

	// 1 const修饰指针 常量指针
	const int* p = &a;
	// *p = 10; //err
	p = &b;

	// 2 const修饰常量 
	int* const p2 = &a;
	*p2 = 10;
	//p2 = &b;// err

	// 3 const修饰指针和常量
	const int* const p3 = &a;
	//*p3 = 20; // err
	//p3 = &b;// err

	system("pause");
	return 0;
}

7.6 指针和数组

作用:利用指针来访问数组中的元素

示例:

#include <iostream>
using namespace std;

int main()
{
	int arr[5] = { 1,2,3,4,5 };
	int* p = arr;// 指向数组的首地址

	cout << "第一个元素:"<< * p << endl;
	cout <<"指针访问第一个元素:"<< * p << endl;

	for (int i = 0; i < 5; i++)
	{
		//cout << arr[i];
		cout << *p << endl;
		p++;
	}

	system("pause");
	return 0;
}

7.7 指针和函数

作用:利用指针做函数参数,在函数内可以修改实参的值。

示例:

#include <iostream>
using namespace std;

void swap(int* p1, int* p2) {
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

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

	// 地址传递参数
	swap(&a, &b);
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;

	system("pause");
	return 0;
}

总结:如果不想改变实参值,就用值传递;想改变实参的值,就用地址传递。

7.8 指针、数组和函数

案例:封装一个函数,使用指针形参,利用冒泡排序,实现对整型数组的升序排序。

#include <iostream>
using namespace std;

void sort(int* arr, int len) {
	for (int i = 0; i < len-1; i++)
	{
		for (int j = 0; j < len - 1 - i; j++) {
			if (arr[j] > arr[j + 1]) {
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}

void printArr(int* p, int len) {
	for (int i = 0; i < 10; i++) {
		cout << *p << endl;
		p++;
	}
}

int main()
{
	int arr[10] = { 2,4,6,8,0,1,3,5,7,9 };

	sort(arr, 10);
	printArr(arr, 10);

	system("pause");
	return 0;
}

9 结构体

9.1 结构体的基本概念

结构体属于用户自己定义的数据类型,运行用户存储不同的成员元素数据类型。

9.2 结构体定义和使用

语法:

struct 结构体名{

结构体成员列表

};

结构体成员列表是一些数据类型变量定义。

结构体创建变量的方式有三种:

  1. struct 结构体名 变量名;
  2. struct 结构体名 变量名 = {成员值1,成员值2……}
  3. 定义结构体时在{}后面顺便定义了变量名;

示例:

#include <iostream>
using namespace std;

struct Student {
	string name;
	int age;
	int score;
}s;  // 第3种定义方式

int main()
{
	// 第1种定义方式
	struct Student s1;
	s1.name = "andy";
	s1.age = 18;
	s1.score = 100;
	cout << "name:" << s1.name << " age:" << s1.age << " score:" << s1.score<<endl;

	// 第2种定义方式
	struct Student s2 = {"echo",19,99};
	cout << "name:" << s2.name << " age:" << s2.age << " score:" << s2.score << endl;

	// 第三种定义方式的赋值
	s.name = "helly";
	s.age = 20;
	s.score = 80;
	cout << "name:" << s.name << " age:" << s.age << " score:" << s.score << endl;

	s = { "test",30,70 };
	cout << "name:" << s.name << " age:" << s.age << " score:" << s.score << endl;

	system("pause");
	return 0;
}

9.3结构体数组

作用:将自定义的结构体放到数组中维护。

语法:struct 结构体名 数组名[元素个数] = {{结构体成员值1},{结构体成员值2}……}

示例:

#include <iostream>
using namespace std;

struct Student {
	string name;
	int age;
	int score;
};  

int main()
{
	// 结构体数组
	struct Student s[3] = {
		{"echo",19,99} ,
		{"echo2",29,89} ,
		{"echo3",39,79}
	};

	s[2].name = "helly";
	s[2].age = 20;
	s[2].score = 80;
	for (int i = 0; i < 3; i++) {
		cout << " name:" << s[i].name
			<< " age:" << s[i].age
			<< " score:" << s[i].score
			<< endl;
	}

	system("pause");
	return 0;
}

9.4 结构体指针

作用:通过指针来访问结构体中的成员变量。

结构体指针利用  -> 来访问结构体成员变量。 

示例:

#include <iostream>
using namespace std;

struct Student {
	string name;
	int age;
	int score;
};  

int main()
{
	// 结构体数组
	struct Student s = { "echo",19,99 };
	Student* p = &s;

	// 结构体指针用 -> 来访问结构体成员变量
	cout << " name:" << p->name
		<< " age:" << p->age
		<< " score:" << p->score
		<< endl;

	system("pause");
	return 0;
}

9.5 结构体嵌套结构体

作用:结构体中的成员可以是另一个结构体。

示例:

#include <iostream>
#include<string>

using namespace std;

struct Student {
	string name;
	int age;
	int score;
};

struct Teacher {
	int id;
	string name;
	Student s;
};

int main()
{
	Student s1 = { "echo",19,99 };
	Teacher t = { 1,"张三",s1 };

	// 结构体指针用 -> 来访问结构体成员变量
	cout << "老师的信息:id:" << t.id
		<< " name:" << t.name
		<< " 所带学生信息:name:" << t.s.name
		<< " age:" << t.s.age
		<< " score:" << t.s.score
		<< endl;

	system("pause");
	return 0;
}

9.6 结构体做函数参数

作用:将结构体作为参数传递到函数中

传递方式有两种:

  • 值传递
  • 地址传递

示例:

#include <iostream>
#include<string>

using namespace std;

struct Student {
	string name;
	int age;
	int score;
};

// 打印
// 1 值传递 不会修改到结构体中实参的值
void printStudent1(Student s) {
	s.age = 100;
	cout << "printStudent1 name:" << s.name << " age:" << s.age << " score:" << s.score << endl;
}

// 打印
// 2 地址传递  会修改到结构体中实参的值
void printStudent2(Student* s) {
	s->age = 200;
	cout << "printStudent2 name:" << s->name << " age:" << s->age << " score:" << s->score << endl;
}

int main()
{
    Student s = { "echo",19,99 };

	printStudent1(s);
	cout << "main: name:" << s.name << " age:" << s.age << " score:" << s.score << endl;

	printStudent2(&s);
	cout << "main: name:" << s.name << " age:" << s.age << " score:" << s.score << endl;

	system("pause");
	return 0;
}

9.7 结构体中const

作用:用const防止修改的误操作。

示例:

#include <iostream>
#include<string>

using namespace std;

struct Student {
	string name;
	int age;
	int score;
};

// 打印
// 形参用指针可以节省空间,而且不会复制新的副本
void printStudent2(const Student* s) {
	// s->age = 200;// 会直接报错
	cout << "printStudent2 name:" << s->name << " age:" << s->age << " score:" << s->score << endl;
}

int main()
{
    Student s = { "echo",19,99 };

	printStudent2(&s);
	cout << "main: name:" << s.name << " age:" << s.age << " score:" << s.score << endl;

	system("pause");
	return 0;
}

总结:指针前加了const修饰之后,就变成了只读变量不能在函数内部修改,防止误修改。

1 ASCII 编码一览表

SCII 编码一览表(十进制0-31、127为控制字符,其他为可显示字符)
二进制十进制十六进制字符/缩写解释
00000000000NUL (NULL)空字符
00000001101SOH (Start Of Headling)标题开始
00000010202STX (Start Of Text)正文开始
00000011303ETX (End Of Text)正文结束
00000100404EOT (End Of Transmission)传输结束
00000101505ENQ (Enquiry)请求
00000110606ACK (Acknowledge)回应/响应/收到通知
00000111707BEL (Bell)响铃
00001000808BS (Backspace)退格
00001001909HT (Horizontal Tab)水平制表符
00001010100ALF/NL(Line Feed/New Line)换行键
00001011110BVT (Vertical Tab)垂直制表符
00001100120CFF/NP (Form Feed/New Page)换页键
00001101130DCR (Carriage Return)回车键
00001110140ESO (Shift Out)不用切换
00001111150FSI (Shift In)启用切换
000100001610DLE (Data Link Escape)数据链路转义
000100011711DC1/XON
(Device Control 1/Transmission On)
设备控制1/传输开始
000100101812DC2 (Device Control 2)设备控制2
000100111913DC3/XOFF
(Device Control 3/Transmission Off)
设备控制3/传输中断
000101002014DC4 (Device Control 4)设备控制4
000101012115NAK (Negative Acknowledge)无响应/非正常响应/拒绝接收
000101102216SYN (Synchronous Idle)同步空闲
000101112317ETB (End of Transmission Block)传输块结束/块传输终止
000110002418CAN (Cancel)取消
000110012519EM (End of Medium)已到介质末端/介质存储已满/介质中断
00011010261ASUB (Substitute)替补/替换
00011011271BESC (Escape)逃离/取消
00011100281CFS (File Separator)文件分割符
00011101291DGS (Group Separator)组分隔符/分组符
00011110301ERS (Record Separator)记录分离符
00011111311FUS (Unit Separator)单元分隔符
001000003220(Space)空格
001000013321!
001000103422"
001000113523#
001001003624$
001001013725%
001001103826&
001001113927'
001010004028(
001010014129)
00101010422A*
00101011432B+
00101100442C,
00101101452D-
00101110462E.
00101111472F/
0011000048300
0011000149311
0011001050322
0011001151333
0011010052344
0011010153355
0011011054366
0011011155377
0011100056388
0011100157399
00111010583A:
00111011593B;
00111100603C<
00111101613D=
00111110623E>
00111111633F?
010000006440@
010000016541A
010000106642B
010000116743C
010001006844D
010001016945E
010001107046F
010001117147G
010010007248H
010010017349I
01001010744AJ
01001011754BK
01001100764CL
01001101774DM
01001110784EN
01001111794FO
010100008050P
010100018151Q
010100108252R
010100118353S
010101008454T
010101018555U
010101108656V
010101118757W
010110008858X
010110018959Y
01011010905AZ
01011011915B[
01011100925C\
01011101935D]
01011110945E^
01011111955F_
011000009660`
011000019761a
011000109862b
011000119963c
0110010010064d
0110010110165e
0110011010266f
0110011110367g
0110100010468h
0110100110569i
011010101066Aj
011010111076Bk
011011001086Cl
011011011096Dm
011011101106En
011011111116Fo
0111000011270p
0111000111371q
0111001011472r
0111001111573s
0111010011674t
0111010111775u
0111011011876v
0111011111977w
0111100012078x
0111100112179y
011110101227Az
011110111237B{
011111001247C|
011111011257D}
011111101267E~
011111111277FDEL (Delete)删除

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值