C++基础入门
1、创建项目
这里使用的是Visual Studio
输入好自己的项目名称,然后选择位置后即可
新建源文件,在这个位置右键
选择C++文件,取好名字添加即可
2、HelloWorld
那么我们就可以开始写第一个程序了,
#include <iostream>
using namespace std;
int main()
{
cout << "hello C++" << endl;
system("pause");
return 0;
}
点击本地windows调试器,就输出了
3、注释
作用:在代码中加入一些说明和解释,方便自己或其他人阅读
在运行时,编译器会忽略这些注释的内容
两种格式
1、单行注释
//
通常放在一行代码的上方,或者一条语句的末尾,对该行代码说明
2、多行注释
/* 这是多条注释*/
通常放在一段代码的上方,对该段代码做整体说明
4、变量
作用:给一段指定的内存空间起名,方便操作这段内存
注意这个变量顾名思义,就是可以改变的数值
语法:数据类型 变量名 = 初始值;
如上图所示,每块内存都有它自己的编号(0x0000),我们可以用编号来使用它,但是不便于管理,这时候我们将它取一个便于记住的名字(a),那么a
就是变量名
#include<iostream>
using namespace std;
int main() {
//变量创建的语法:数据类型 变量名 = 变量初始值
int a = 10;
cout << "a = " << a << endl;
system("pause");
return 0;
}
5、常量
作用:用于记录程序中不可更改的数据
注意:这里的值不可以改变
#define
宏常量: #define 常量名 常量值- 通常在文件上方定义,表示一个常量
const
修饰常量:const 数据类型 常量名 = 常量值- 通常在变量定义前加关键字const,修饰该变量为常量
#include<iostream>
using namespace std;
/*
常量的定义方式
1、#define 宏常量
2、const修饰的常量
*/
//1、#define 宏常量
#define Day 7
int main() {
//Day = 14 这是不可以修改的 Day为常量,一旦修改就会报错
cout << "一周一共有:" << Day << "天" << endl;
//2、const 修饰常量
const int month = 30;
// month = 24 这里也是不可以修改的
cout << "一月一共有:" << month << "天" << endl;
system("pause");
return 0;
}
6、关键字
作用:关键字是C++中预先保留的单词
注意:在定义变量或者常量时不要使用
7、命名规则
- 标识符不能是关键字
- 标识符只能由字母、数字、下划线组成
- 第一个字符必须为字母或下划线
- 标识符中字母区分大小写
给变量取名的时候做到见名知意
8、数据类型
C++规定在创建一个变量或者常量时,必须要制定出相对应的数据类型,否则无法给变量分配内存
8.1、整型
作用:整型变量表示整数的数据
以下在C++中有几种类型方式表示整型,区别在于内存空间不同
数据类型 | 占用空间 | 取值范围 |
---|---|---|
short(短整型) | 2字节 | (-215~215-1) |
int(整型) | 4字节 | (-231~231-1) |
long(长整型) | windos为4字节,linux为4字节(32位),8字节(64位) | (-231~s31-1) |
long long(长长整型) | 8字节 | (-263~263-1) |
值不可以超过这个取值范围不然会出错,c++会自动变成负数的第一位,依次类推
#include<iostream>
using namespace std;
int main() {
//1、短整型(-32768~32767)
short num1 = 10;
//2、整型
int num2 = 10;
//3、长整型
long num3 = 10;
//4、长长整型
long long num4 = 10;
cout << "num1 = " << num1 << endl;
cout << "num2 = " << num2 << endl;
cout << "num3 = " << num3 << endl;
cout << "num4 = " << num4 << endl;
system("pause");
return 0;
}
8.2、sizeof关键字
作用:利用sizeof关键字可以统计数据类型所占内存大小
语法:sizeof(数据类型/变量
#include<iostream>
using namespace std;
int main() {
//利用sizeof求出数据类型占用的内存大小
short num1 = 10;
cout << "short占用的内存空间为:" << sizeof(num1) << endl;
int num2 = 10;
cout << "int占用的内存空间为:" << sizeof(num2) << endl;
long num3 = 10;
cout << "long占用的内存空间为:" << sizeof(num3) << endl;
long long num4 = 10;
cout << "long long占用的内存空间为:" << sizeof(num4) << endl;
system("pause");
return 0;
}
8.3、实型(浮点型)
作用:用于表示小数
浮点型变量分为两种:
- 单精度float
- 双精度double
两者的区别在于表示有效数字的范围不同
数据类型 | 占用空间 | 有效数字范围 |
---|---|---|
float | 4字节 | 7位有效数字 |
double | 8字节 | 15~16位有效数字 |
有效数字
:例如3.14 这里的有效数字就为3位
c++中不管是单精度还是双精度默认只显示6位数字
#include<iostream>
using namespace std;
int main() {
//1、单精度 float
//这里加f的意思是让C++当成单精度处理,不然会自动转成双精度再转换成单精度
float f1 = 3.142131f;
cout << "f1=" << f1 << endl;
cout << "float的内存空间" << sizeof(f1) << endl;
//2、双精度
double f2 = 3.1322312;
cout << "f2=" << f2 << endl;
cout << "double的内存空间" << sizeof(f2) << endl;
//科学计数法
float f3 = 3e2; //3*10 ^ 2
cout << "f2=" << f3 << endl;
float f4 = 3e-2; //3*0.1 ^ 2
cout << "f4=" << f4 << endl;
system("pause");
return 0;
}
8.4、字符型
作用:字符型变量用于显示单个字符
语法:char ch = ‘a’;
注意:
- 再显示字符型变量时,要用
单引号
括起来,不要用双引号 - 单引号内只能有一个字符,不可以是字符串
c和c++中字符型变量值占用1个字节
字符型变量并不帅把字符串本身放到内存中存储,而是将对应的ASCII编码
放入到存储单元
#include<iostream>
using namespace std;
int main() {
char a = 'a';
cout << "char所占内存空间" << sizeof(a) << endl;
//字符型变量的常见错误
//char c = "b"; //创建字符型变量时候,要用单引号
//char c = 'asdsad'; //创建字符型变量时候,单引号只能有一个
//4、字符型变量对应的ASCII编码
// a = 97
// A = 65
char ch1 = 'a';
cout << "a的ASCII编码" << (int)ch1 << endl;
char ch2 = 'A';
cout << "A的ASCII编码" << (int)ch2 << endl;
system("pause");
return 0;
}
8.5、转义字符
作用:用于表示一些不能显示出来的ASCII字符
这里我只列举一些常用的
转义字符 | 含义 | ASCII码值 |
---|---|---|
\n | 换行 | 010 |
\ | 表示一个反斜杠字符"\" | 092 |
\t | 水平制表(跳到下个TAB位置) | 009 |
#include<iostream>
using namespace std;
int main7() {
//1、单精度 float
//这里加f的意思是让C++当成单精度处理,不然会自动转成双精度再转换成单精度
float f1 = 3.142131f;
cout << "f1=" << f1 << endl;
cout << "float的内存空间" << sizeof(f1) << endl;
//2、双精度
double f2 = 3.1322312;
cout << "f2=" << f2 << endl;
cout << "double的内存空间" << sizeof(f2) << endl;
//科学计数法
float f3 = 3e2; //3*10 ^ 2
cout << "f2=" << f3 << endl;
float f4 = 3e-2; //3*0.1 ^ 2
cout << "f4=" << f4 << endl;
system("pause");
return 0;
}
8.6、字符串型
作用:用于表示一串字符
语法:string 变量名 = “字符串值”
#include<iostream>
using namespace std;
int main() {
string str = "hello world";
cout << str << endl;
system("pause");
return 0;
}
如果报错的话,可以加一个头文件#include<string>
8.7、布尔类型
作用:布尔数据类型代表真或者假的值
bool类型只有俩个值
- true 表示 真 可以用 1 来表示
- flase 表示 假 可以用 0 来表示
bool类型占1个字节大小
#include<iostream>
using namespace std;
int main() {
bool flag = true;
cout << flag << endl;
bool flag1 = false;
cout << flag1 << endl;
cout <<"bool占的内存空间:" << sizeof(flag1) << endl;
system("pause");
return 0;
}
8.8 、数据的输入
作用:用于从键盘获取数据
关键字: cin
语法: cin>>变量
9、数组
定义方式
- 数据类型 数组名 [数组长度];
#定义
int arr[5];
#存数组
arr[0] = 10;
#输出
cout<<arr[0]<<endl;
- 数据类型 数组名[数组长度] = {值1,值2,…}
#定义
#初始化没有定义值为0
int arr2[5] = { 10,20,30,40,50 };
cout << arr2[1] << endl;
- 数据类型 数组名[] = {值1,值2,…}
int arr3[] = { 30,20,10 };
9.1、一维数组
- 可以统计整个数组在内存中的长度
int arr[4] = { 1,2,3,4 };
cout << sizeof(arr) << endl;
//16
- 可以获取数组在内存中的首地址
cout << (int)arr << endl;
//& 元素的首地址
cout << (int)&arr << endl;
冒泡排序
int arr[9] = { 4,2,8,0,5,7,1,3,9 };
cout << "排序前:" << endl;
for (int i = 0; i < 9; i++)
{
cout << arr[i] << "";
}
for (int i = 0; i < 9 - 1; i++)
{
for (int j = 0; j < 9-i-1; j++)
{
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
cout << "排序后:" << endl;
for (int i = 0; i < 9; i++)
{
cout << arr[i] << "";
}
9.2、二维数组
//1.数据类型 数组名[行数][列数]
int arr[2][3];
//赋值
arr[0][0] = 1;
// 2.数据类型 数组名[行数][列数] = {{数据1,数据2},{数据3,数据4}}
int arr2[2][3] = {
{1,2,3},
{4,5,6}
};
// 3.数据类型 数组名[行数][列数] = {数据1,数据2,数据3,数据4};
int arr3[2][3] = { 1,2,3,4,5,6 };
// 4. 数据类型 数组名[ ][列数] = {数据1,数据2,数据3,数据4};
//这里可以自动推断行数,但不能省列数
int arr4[][3] = { 1,2,3,4,5,6 };
可利用循环来做打印或赋值
外层循环打印行,内层循环打印列
//行
for (int i = 0; i < 2; i++)
{
//列
for (int j = 0; j < 3; j++)
{
cout << arr[i][j] << " ";
}
cout << endl;
}
9.2.1、二维数组名称
用途
- 查看二维数组所占用的内存空间
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;
- 获取二维数组首地址
cout << "二维数组地址" << (int)arr << endl;
//第一行和第二行相差12字节
cout << "二维数组第一行地址" << (int)arr[0] << endl;
cout << "二维数组第二行地址" << (int)arr[1] << endl;
//第一个和第二个元素相差4字节
cout << "二维数组第一个元素地址" << (int)&arr[0][0] << endl;
cout << "二维数组第二个元素地址" << (int)&arr[0][1] << endl;
10、函数
作用:将一段经常使用的代码封装起来,减少重复代码
10.1、函数的定义
- 函数值类型
- 函数名
- 参数表列
- 函数体语句
- return表达式
语法:
返回值类型 函数名(参数列表)
{
函数体语句
return表达式
}
//eg 加法
int add(int num1, int num2) {
int sum = num1 + num2;
return sum;
};
10.2、函数的调用
int main() {
int a = 1;
int b = 2;
cout << add(a, b) << endl;
system("pause");
return 0;
}
10.3、 值传递
void 无类型,不需要返回值 不影响实参
//不影响实参
void swap(int num1, int num2) {
int temp = num1;
num1 = num2;
num2 = temp;
cout << "交换后" << endl;
cout << "num1" << num1 << endl;
cout << "num2" << num2 << endl;
}
10.4、函数的常见样式
常见的函数样式4种
- 无参无返
void test01() {
cout << "1213" << endl;
}
int main() {
//无参无返
test01();
system("pause");
return 0;
}
- 有参无返
void test02(int a ) {
cout << "有参无返" << a << endl;
}
int main() {
//有参无返
test02(1);
system("pause");
return 0;
}
- 无参有返
int test03() {
cout << "123" << endl;
return 100;
}
int main() {
//无参有反
test03();
system("pause");
return 0;
}
- 有参有返
//有参有返
int test04(int a) {
return a + 1;
}
int main() {
cout<<test04(3);
system("pause");
return 0;
}
10.5、函数的声明
提前告诉编译器函数存在,避免报错,可以把函数放在main的后面。
- 声明和定义的区别
- 声明没有具体代码
- 声明可以写多次,定义只能一次
//声明
int max(int a, int b);
int main() {
int a = 1;
int b = 2;
cout<<max(a, b);
system("pause");
return 0;
}
//定义
int max(int a, int b) {
return a > b ? a : b;
}
10.6、函数的分文件编写
使代码可读性更高,不堆积在一个文件中
创建步骤
- 创建.h后缀的头文件
- 创建.cpp后缀名的源文件
- 在头文件中写函数的声明
- 在源文件中写函数的定义
11、指针
作用:利用指针来访问内存(指针就是一个地址)
& 与 * 互为逆运算。& ,其作用是取变量的地址;* ,其作用是取地址对应的内存
- 定义
数据类型 * 指针变量名
int a = 10;
//指针定义的语法:数据类型 * 指针变量名;
int * p;
//让指针记录变量a的地址
p = &a;
//输出
cout << "a的地址:" << &a << endl;
cout << "指针P为:" << p << endl;
- 使用
利用解引用
的方式来找到指针指向的内存
指针前加*
代表解引用
,找到指针指向内存中的数据
//使用指针
*p = 1000;
//此时a的值为1000
cout << "a=" << a << endl;
cout << "*p=" << *p << endl;
11.1、指针占用的内存
指针所占用的空间跟操作系统有关,32位和64位操作系统
- 64位操作系统
int a = 10;
int* p = &a;
cout << "64位操作系统下占用的内存空间int:" << sizeof(int *) << endl;
cout << "64位操作系统下占用的内存空间float:" << sizeof(float *) << endl;
cout << "64位操作系统下占用的内存空间double:" << sizeof(double *) << endl;
cout << "64位操作系统下占用的内存空间char:" << sizeof(char *) << endl;
- 32位操作系统
11.2、空指针和野指针
空指针和野指针均不是我们所申请的空间,所以都不要访问
空指针
:指针变量指向内存中编号为0的空间(0~255为系统占用不可访问)
用途
:初始化指针变量
注意
:空指针指向的内存不可访问
//初始化
int *p = null;
//空指针访问(会报错)
*p = 100;
野指针
:指向一个非法内存空间(随意指向一个内存地址),不是自己申请的。
//指针变量p指向0x111的空间
int * p = (int *)0x111;
cout << *p<< endl;
11.3、const修饰指针
- coust修饰
指针
—常量指针
- coust修饰
常量
—指针常量
- coust修饰
指针
和常量
常量指针
(只能修改指针指向的地址,不能修改值)
int a = 10;
int b = 20;
const int * p = & a;
//指向可修改,值不可被修改
p = &b;
*p = 20;//错误
指针常量
(只能修改值,不能修改指向地址)
int a = 10;
int b = 20;
int * const p = &a;
//指向不可被修改,值可被修改
*p = 20;
p = &b;//错误
- coust修饰
指针
和常量
(俩个均不可被修改)
int a = 10;
int b = 20;
const int* const p = &a;
//均不可被更改
*p = 20;
p = &b;
11.4、指针数组
利用指针访问数组中的元素
int arr[5] = { 1,2,3,4,5 };
//利用指针指向数组首地址
int * p = arr;
for (int i = 0; i < 5; i++)
{
cout << *p << endl;
cout << &*p << endl;
//使地址每次向后移
p++;
}
11.5、指针和函数
地址传递
:当我们函数传入的是地址时,可以改变实参的数据
void swap(int* p1, int* p2) {
int temp = *p1;//将值赋给temp
*p1 = *p2;//将值赋给p1
*p2 = temp;
}
int main() {
int a = 10;
int b = 20;
cout << "a:" << a << endl;
cout << "b:" << b << endl;
swap(a, b);
cout << "改变后a:" << a << endl;
cout << "改变后b:" << b << endl;
system("pause");
return 0;
}
值传递和地址传递区别
:值传递不改变值,地址传递改变参数的值
12.结构体
允许
用户自定义
的数据类型,允许用户存储不同的数据类型
-
语法
//自定义数据类型,一些类型的集合组成的一个类型 //语法:struct 类型名称{}
struct Student { //姓名 string name; //年龄 int age; //分数 int score; };
-
赋值
- 通过声明一个名字给它的属性赋值
int main() { //直接声明赋值 struct Student s1; s1.name = "张三"; s1.age = 11; s1.score = 100; cout << "name:" << s1.name << "age:" << s1.age << "score:" << s1.score; system("pause"); return 0; }
- 直接赋值
struct Student s2 { "李四", 17, 200 }; cout << "name:" << s2.name << "age:" << s2.age << "score:" << s2.score << endl;;
- 创建结构体时创建结构体变量(不推荐)
struct Student { //姓名 string name; //年龄 int age; //分数 int score; }s3;
struct
在c++中创建变量时可以可以省略,定义结构体不可被省略
Student s2
{
"李四",
17,
200
};
12.1、结构体数组
将自定义的结构体放入到数组中方便维护
语法
:数据类型 数组名 = { {…},{…},… }
struct Student
{
string name;
int age;
int score;
};
int main() {
Student stdArray[3] = {
{"张三",11,122},
{"李四",12,111},
{"王五",13,322}
};
//修改元素
stdArray[2].age = 100;
cout << stdArray[2].age << endl;
//输出
for (int i = 0; i < 3; i++)
{
cout << "姓名:" << stdArray[i].name << endl;
}
system("pause");
return 0;
}
12.2、结构体指针
通过指针访问结构体中的成员
- 利用操作符·
->
可以通过指针访问结构体属性
struct Student
{
string name;
int age;
int score;
};
int main() {
Student s1 = { "张三",11,200 };
Student * p = &s1;
cout << p->name << p->age << p->score;
system("pause");
return 0;
}
12.3 、结构体嵌套结构体
结构体中的成员可以是另一个结构体
struct Student
{
string name;
int age;
int score;
};
struct Teacher
{
string name;
int age;
Student stu;
};
int main() {
Teacher t;
t.age = 1;
//访问结构体中的结构体
t.stu.age = 1;
return 0;
}
12.4、结构体做函数参数
将函数体作为参数向函数中传递
传递的俩种方式
- 值传递
- 地址传递
想修改主函数中的数据地址传递,反之值传递
值传递
函数里面形参会发生变化,实参不会改变
//定义结构体
struct Student
{
string name;
int age;
int score;
};
//输出
void printStudent(Student stu) {
stu.age = 100;
cout <<"修改后age:" << stu.age<<endl;
}
int main() {
Student s1 = {
"zy",
11,
12
};
cout << "修改前age:" << s1.age << endl;
printStudent(s1);
cout << "执行完age:" << s1.age << endl;
t.stu.age = 1;
return 0;
}
地址传递
:可通过地址修改实参
//定义结构体
struct Student
{
string name;
int age;
int score;
};
//输出
void printStudent2(Student * p) {
p->age = 200;
cout << "修改后age:" << p->age << endl;
}
int main() {
Student s1 = {
"zy",
11,
12
};
cout << "修改前age:" << s1.age << endl;
//printStudent(s1);
printStudent2(&s1);
cout << "执行完age:" << s1.age << endl;
t.stu.age = 1;
return 0;
}
12.5、结构体中const使用场景
用const来防止误操作
void printStudent(const Student * p) {
//不可被修改
//p->age = 100;
cout <<"修改后age:" <<p->age<<endl;
}