C++基础入门

1.C++概述

C++是一门很强大很难学的计算机编程语言。

2.运行环境

Visual Studio 2020

3.基础知识

3.1 注释

//在C++中双斜杠//表示单行注释

/*
	/*...*/表示多行注释内容
*/

3.2 第一个程序

#include<iostream>
//in,out,stream 输入输出流,即表示引入输入输出流库

using namespace std;
//using表示利用,namespace表示命名空间,std表示标准,C++语言每行结束需要加分号;cout属于std
//可以不用写using namespace std;直接在代码中写std::cout

int main(){
    //main()函数为程序的入门(程序从这开始执行)
    cout << "Hellow World!" << endl;
    //打印"Hellow World!"语句,cout为输出函数
    
    return 0;
    //程序运行结束后返回0,可省略改行代码,	
    //C++文件运行启动一个进程,返回码为0,若return -1,则返回码为-1
}

3.3 常量

#include<iostream>
using namespace std;

#define X "Hellow World!"
#define Y "Autumn"
//打印X,Y时会将后面的语句进行替换打印

#define Z 1+2
#define Q (1+2)
//意义不同,代入表达式的优先级运算不同

const int b = 1;
//变量b变为常量,不可被修改

int main(){
    cout << endl;
    //endl表示空行,会打印空行
    
    cout << X << Y << endl;
    //X,Y不换行打印
    //输出Hellow World!Autumn
    
    cout << X << endl << Y << endl;
    //X,Y之间换行打印
	
    cout << Z * Z;
    //1+2 * 1+2 = 5
    
    cout << Q * Q'
    //(1+2)*(1+2) = 9
    
    return 0;
}

3.4 变量

1.C++语言中变量大小写敏感

2.C++保留的关键字无法用做变量名

3.变量命名规则

​ a.只能由数字,字母,下划线组成,且数字不放开头

​ b.字母区分大小写

#include<iostream>
using namespace std;
int main(){
    //变量的定义(数据类型 变量名 = 初始值;)
	int i = 1;
	int x = 0 + 2;
    
    //变量的打印准则
    cout << "i = " << i << endl;
    cout << "x = " << x << endl;
    //打印 i = 1
    //    x = 2
    
    //未初始化变量打印会报错
    
//整形变量
    /*
    整形变量  字节数(一个字节等于八位)  表示范围
	short      2						2^16(-2^15——2^15-1)
	int		   4						2^32(-2^31——2^31-1)
	long       4						2^32(-2^31——2^31-1)
	long long  8						2^64(-2^63——2^63-1)
    */
    
    //sizeof关键字获取变量位数
    short x = 1;
    int y = 2;
    cout << sizeof(short) << endl;
    cout << sizeof(x) << endl;
    //12
    
    cout << sizeof(int) << endl;
    cout << sizeof(y) << endl;
    //24
    
    cout << sizeof(long) << endl;
	cout << sizeof(long long) << endl;
    //48
    
    
//浮点数(小数)
    /*
    	float    4字节
		double   8字节
    */
    
    float x = 3.1415926f;
    //通常在后面加上f表示浮点数
    
    double y1 = 3.1415926;
    
    double y2 = 1.5e5;
    //1.5e5表示e后乘上10^5
    
    double y3 = 1.5e-5;
    //1.5e-5为10的-5次方
    
    cout << setprecision(7) << x << endl;
    //setprocision()表示操控精度,7表示全部位数
    
    double y4 = 1.0 / 2789347 * 2789347;
	//f5 = 0.99999999998987
    
    //double fabs(double x) 返回浮点数 x 的绝对值。
	/*fabs()用于计算一个数的绝对值。这个函数在处理数学运算时非常有用,可以确保获得数值的非负表示。*/
    
    if (fabs(y4 - 1) < 0.00000001){
        cout << "y4的精度小于0.00000001" << endl;
    }
    //比较浮点数的绝对值,以确定其是否在某个误差范围内与目标值相等。
    
    
//字符型
    char c = 'a';
    //char c = "a";不能用双引号,双引号用于字符串。
    
    cout << c << endl;
    cout << sizeof(c) << endl;
    //a1
    
    //强转字符
    char a = 'a';
    char b = 'b';
    cout << (int)a << endl;
    cout << (int)b << endl;
    cout << b-a << endl;
    //字符在内存中存储为数字,a == 97,b == 98,b - a == 1
        
//字符串型
	//char 变量名[] = "字符串常量";
	char c6[] = "英雄算法联盟";
	cout << sizeof(c6) << endl;
	//每个字两个字节,加上结尾存在一个\0,一个13个字节

	//第二种字符串表示方法
	//string,先导入string库
	string c7 = "夜深人静写算法";
	cout << c7 << endl;

//布尔类型(真和假)
	bool flag1 = true; //真
	bool flag2 = false;//假
	cout << flag1 << flag2 << endl;
	//输出0,1
    
	cout << sizeof(bool) << endl;
    
	//取反操作
	flag1 = !flag1;
	cout << flag1 << endl;
    
//转义字符
    char c1 = '\a';
	cout << (int)c1 << endl;
    
	char c2 = '\n';
	cout << (int)c2 << endl;
	cout << "c2为换行语句" << c2;
    
	//\n为换行,\t为制表符(空格),\\表示\,\0为忽略后面的字符,\077则表示八进制数,\"表示"
    
    
    
    
//数据的输入和输出
    //1.整形的输入
    int i1 = 5;
    cin >> i1;
    cout << "i1的值变为了" << i1 << endl;

    //2.浮点型的输入
    double d1 = 3.1;
    cin >> d1;
    cout << "d1的值变为了" << d1 << endl;

    //3.字符型的输入
    char ch1 = 'a';
    cin >> ch1;
    cout << "ch1的值变为了" << ch1 << endl;

    //4.字符串型
    string st = "abc";
    cin >> st;
    cout << "st的值变为了" << st << endl;


    //5.布尔型
    bool bo = true;
    cin >> bo;
    cout << "bo的布尔值变为了" << bo << endl;
    
    
    
//算书运算符号
	int i3 = 1;
	int i4 = 2;
	cout << i3 + i4 << endl;
	cout << i3 - i4 << endl;
	cout << i3 * i4 << endl;
	cout << i3 / i4 << endl;
    //两整数相除为整除,
	
    cout << i3 * 1.0 / i4 << endl;
    //浮点数相运算会出现小数   
    
//越界
	int i5 = 10000000;
	int i6 = 100000;
	cout << i5 * i6 << endl;//i5 * i6的结果会越界
    
    //解决办法
	cout << (long long)i5 * i6 << endl;//强转类型
    
    int i7 = -1;
	int i8 = 2;
	cout << i7 / i8 << endl;//结果为0,会截断小数点部分
    
    int i9 = -1;
    int i10 = -i9;
    cout << i9 << " " << i10 << endl;//-符号化为取反,无--符号,可以-(-a)
    
    
    
    return 0;
}

3.5 数据的输入输出及运算符

#include<iostream>
using namespace std;

int main(){
    
//数据的输入和输出
    //1.整形的输入
    int i1 = 5;
    cin >> i1;
    cout << "i1的值变为了" << i1 << endl;

    //2.浮点型的输入
    double d1 = 3.1;
    cin >> d1;
    cout << "d1的值变为了" << d1 << endl;

    //3.字符型的输入
    char ch1 = 'a';
    cin >> ch1;
    cout << "ch1的值变为了" << ch1 << endl;

    //4.字符串型
    string st = "abc";
    cin >> st;
    cout << "st的值变为了" << st << endl;


    //5.布尔型
    bool bo = true;
    cin >> bo;
    cout << "bo的布尔值变为了" << bo << endl;
    
    
    
//算书运算符号
	int i3 = 1;
	int i4 = 2;
	cout << i3 + i4 << endl;
	cout << i3 - i4 << endl;
	cout << i3 * i4 << endl;
	cout << i3 / i4 << endl;
    //两整数相除为整除,
	
    cout << i3 * 1.0 / i4 << endl;
    //浮点数相运算会出现小数   
    
//越界
	int i5 = 10000000;
	int i6 = 100000;
	cout << i5 * i6 << endl;//i5 * i6的结果会越界
    
    //解决办法
	cout << (long long)i5 * i6 << endl;//强转类型
    
    int i7 = -1;
	int i8 = 2;
	cout << i7 / i8 << endl;//结果为0,会截断小数点部分
    
    int i9 = -1;
    int i10 = -i9;
    cout << i9 << " " << i10 << endl;//-符号化为取反,无--符号,可以-(-a)
    
//字符运算
    char a1 = 'A';
    a1 = a1 + 1;
    cout << a1 << endl;//a1变为B
    
    
//取模运算符%用于两个整数之间,为整除之后的余数
    int integer1 = 100;
    int integer2 = 9;
    cout << integer1 % integer2 << endl;
    //1
    
    int integer1 = -100;
	int integer2 = 9;
	cout << integer1 % integer2 << endl;//-1
	//总结:取模符号和被除数相关(integer1)
    
    
//递增运算符++,递减运算符--
	int integer3 = 1;
	integer3++;//先其他运算再加
	++integer3;//先加再其他运算
	cout << integer3 << endl;

	integer3--;//先其他运算再减
	--integer3;//先减再其他运算
	cout << integer3 << endl;
 
	int integer4 = 1;
	int integer5 = (integer4++) + (++integer4);//1 + 3 = 4
    
    
//赋值运算符 = 
	integer3 = integer3 + integer5;
	integer3 += integer5;
	// x += y // x -= y // x *= y // x /= y // x %= y
    
    
//比较运算符,输出的是布尔值0/1
    ==   等于
    !=  不等于
    <    小于
    >    大于
    <=   小于等于
    >=   大于等于
    cout << (a == b) << endl;//需要加括号
    
    
//逻辑运算符(优先级!>&&>||)
    与 &&
	或 ||
	非 !
    
    //与(关心0和非0)
        cout << (0 && 0) << endl;0
        cout << (0 && 1) << endl;0
        cout << (1 && 0) << endl;0
        cout << (1 && 1) << endl;1

    //或运算
        cout << (0 || 0) << endl;0
        cout << (0 || 1) << endl;1
        cout << (1 || 0) << endl;1
        cout << (1 || 1) << endl;1

    //非
        cout << (!0) << endl;1
        cout << (!1) << endl;0
        
        
//逻辑运算符的嵌套
	int a = !((5 > 4) && (1 - 0) && (1 || 0));
	cout << a << endl;
    
    
//逗号运算符(优先级很低,注意赋值运算)
	int a = 1;
	a = (1 + 2, 3 + 4, 7 + 8);//3,7,15
	cout << a << endl;//15,分别计算并将最后一个值赋值
    
    
//位与运算符(二元)&
    int a = 0b1010;
    int b = 0b1100;
    //      0b1000
    cout << (a & b) << endl;//输出为10进制数
    
    //判断奇偶性
    cout << (5 & 1) << endl;//用一个数来位与1来判断奇偶性 101 001 判断最后一位为0/1来判断奇偶性

    //获取一个二进制数的后五位
    int i = 0b10001010;//01010
    cout << (i & 0b11111) << endl;//位与11111来获取后五位

    //将末五位归零(32位0b111111111111111111111111100000)27个1和5个0
    int j = 0b111111111111111111111111100000;
    cout << (i & j) << endl;

    //消除末尾连续的1
    int i = 0b10101010011111;
    //  i+1 0b10101010100000;
    cout << (i & (i + 1)) << endl;

    //2的幂判定(若为幂则为0b01000000),前提(i > 0)
    int i = 0b0100000;
    //  i-1 0b0011111;
    //      0b0000000; = 0
    cout << ((i > 0) && (i & (i - 1))) << endl;
    
    
//位或 (|)有1即1
    int a = 0b1010;
    int b = 0b1100;
    //      0b1110
    cout << (a | b) << endl;//输出为10进制数

    //设置标志位(让某一位为1)
    int a = 0b10100111;
    int b = 0b10101111;
    //      0b10101111;
    cout << (a | b) << endl;//输出为10进制数

    //置空标记位(让最后一位变零)
    int a = 0b10100111;
    int b = 0b00000001;
    //先变1再减
    cout << ((a | b) - b) << endl;

    //低位连续零变1
    int a = 0b1010011100000;
    //先减1再位或

    int b = 0b1010011111111;
    //先变1再减
    cout << ((a - 1) | a) << endl;
    
    
//异或运算(^),相同为0,不同为1
    int a = 0b10100111;
    int b = 0b10101111;
    //      0b00001000;
    cout << (a ^ b) << endl;//输出为10进制数

    //1.标志位取反(满足交换律和结合律)
    int a = 0b10100111;
    int b = 0b00100000;//第六位为标记位
    //      0b10000111;
    cout << (a ^ b) << endl;//输出为10进制数
    a = (a ^ b);//异或完赋值给a
    
    //2.变量交换(和0异或为本身,和自己异或为0)
	int d = 17;
	int e = 19;
	d = d ^ e;//d` = d ^ e
	e = d ^ e;//d` ^ e = d ^ e ^ e = d ^ 0 = d
	d = d ^ e;//d ^ e ^ d = e
	cout << d << "---" << e << endl;
	//出现奇数次的数
	//加密
    
//按位取反(单目运算符)(~)
    int a = 0b1;
    int b = 0b11111111111111111111111111111110;
    cout << (~a) << endl;//-2,要补全32位
    cout << b << endl;//-2

    //求相反数(按位取反加一)
    int d = 18;
    cout << (~d + 1) << endl;
    
//左移运算符(将操作数x的二进制形式左移y位,相当于乘上2的y次) x << y
    int x = 0b11;//3
    x = (x << y);
    cout << x << endl;//6
    //负数的左移
    int x = -1;
    x = (x << y);
    cout << x << endl;//-2
    //移负数位是不被允许的
    
//右移运算符(x >> y)除以2
    //负数的右移
    //去点低K位
    int a = 0b1001010;//低7位
    cout << (a >> 7) << endl;

    //取第低K位的值(右移4位并与1)
    int a = 0b10010011;
    cout << ((a >> 4) & 1) << endl;
        
    return 0;
    
}
    

4.语句

4.1 if语句

#include<iostream>
using namespace std;
int main(){

    //if语句
	int a;
	cin >> a;
	if (a % 2 == 1)//满足括号里的语句
		cout << "a是一个奇数" << endl;//双引号用于字符串
	//如果if没有加括号就默认执行下面缩进的第一行
    
    //if-else语句
     int a;
     cin >> a;
     if (a & 2) {
            cout << "a是一个奇数" << endl;
        }
     else {
            cout << "a是一个偶数" << endl;
        }
    
// if-else-if -else
	int a = 1;
	if (a == 2) {
		cout << "a是2" << endl;
	}
	else if (a == 3){
		cout << "a是3" << endl;
	}
	else {
		cout << "a是1" << endl;
	}
    
    
    
    return 0;
}

4.2 三目运算符

#include<iostream>
using namespace std;
int main(){
//三目运算符
	// 表达式1 ?表达式2:表达式三;
    //表达式1如果成立则执行表达式2,反之执行表达式3
	x = (a > b ? a = 1 : b = 1);
	cout << x << endl;
    
    
    return 0;
}

4.3 switch语句

#include<iostream>
using namespace std;
int main(){

    //switch语句
    //a语句是一个常量表达式,必须和case后面为同等类型
    int a , cin >> a;
    
	switch (a) {
		case 0:
			cout << "0" << endl;
			break;
		case 1:
			cout << "1" << endl;
			break;
		case '4' - '0':
			cout << "2" << endl;
			break;
		default:
			cout << "default" << endl;


	}
    return 0;
}

4.4 while语句

#include<iostream>
using namespace std;
int main(){

//while语句
	while (cin >> a) {
		cout << a + "写算法" << endl;
	}

	while (cin >> a >> b) {
		cout << a + b + "写算法" << endl;
	}
    
//do-while
	do {
		//执行语句
	} while (1);//先执行一遍再判断条件
    
    return 0;
}

4.5 for()语句

#include<iostream>
using namespace std;
int main(){
    
    //for()语句,a为初始化条件,只执行一次,b为循环的终止条件,c为每次执行完语句就会执行一次,注意各语句的执行顺序
    for(a;  b; c ++)
       {
            d;
       }
    
// int i = 0;
// for(;j <= 1;j ++),放外面
    
// for ( i = 0,sum = 1;j < = i;j ++)
    
// for ( i = 0; ; i ++)//死循环
    
// for ( i = 0; i <= 2; )//把自加放在函数体里
    
    return 0;
}

4.6 终止语句

//break;跳出当前最近的一层循环,跳出switch语法

//continue;结束本次循环,开始下一次循环

5.数组

5.1 一维数组

#include<iostream>
using namespace std;
int main(){
    
// 1. 数组的定义
	// 数据类型 数组名[数字 / 常量表达式];数组下标从0开始
	int a[1024] = {1,2,3,45};
    // int a[1024]; 错误
    
	double b[520];
	char c[1314];
    
    // int n = 1000;
	// int d[n];   错误,[]里不能有变量
    
    
// 2. 数组元素访问
    // 数组名[ 下标 ]
    for (int i = 0; i < 4; ++i) {
        cout << a[i] << endl;
    }
    
    
// 3. 逆序输出
    // 输入一个 n(n < 100),和 n 个数,请逆序输出这个 n 个数
    int n;
    int x[100];
    cin >> n;
    for (int i = 0; i < n; ++i) {
        cin >> x[i];
    }
    for (int i = n - 1; i >= 0; --i) {
        cout << x[i] << ' ';
    }
    cout << endl;
    
    
    return 0;
}

5.2 二维数组

#include <iostream>
using namespace std;

int main() {
	// 1. 二维数组的定义
	// 数组类型 数组名[行][列]
	int arr[3][4];
    
    //赋值方式1
	for (int i = 0; i < 3; ++i) {
		for (int j = 0; j < 4; ++j) {
			arr[i][j] = i * j;
		}
	}
    
    //赋值方式2
	int b[4][4] = {
		{1, 2},
		{2, 3},
		{6,7,8},
		{9,1}
	};
    
    //打印二维数组
	for (int i = 0; i < 4; ++i) {
		for (int j = 0; j < 4; ++j) {
			cout << b[i][j] << ' ';
		}
		cout << endl;
	}



	return 0;
}

6.函数

6.1 函数定义

#include<iostream>
using namespace std;

/*
	1、返回值类型
		1.1 void 空类型:无返回值
		1.2 int 整形:返回整数
		1.3 double/float 浮点型:返回小数
		1.4 char 字符型:返回字符
		
	2、函数名
		知名见意,驼峰原则
	
	3、参数列表
	4、函数体
	5、return 表达式

返回值类型 函数名(参数列表)
{
      函数体
	  return 表达式
}

*/

int add(int a, int b) {
	return a + b;
}

int max(int a, int b)
{
	if (a > b) {
		return a;
	}
	return b;
}

int main(){
    int a = 1;
    int b = 2;
    int c = add(1,2); 
    
    return 0;
}

6.2 函数的调用

#include<iostream>
using namespace std;



int add(int a ,int b){
    int c = a + b;
    return c;
    
}
int max(int a, int b) {
	/*
	if (a > b) {
		return a;
	}
	return b;
	*/
	return a > b ? a : b;
}

int sum(int n) {
	/*int ret = 0;
	for (int i = 1; i <= n; ++i) {
		ret += i;
	}
	return ret;
	*/
	return (1 + n) * n / 2;
    //求和公式


int main(){
	// 1. 加法的调用
	int a = add(1, 7);  // 1 + 7
	int b = add(a, 9);  // a + 9
	cout << a << endl;

	// 2. 最大值的调用
	int c = max(a, b);

	// 3. 求 1 到 n 的和
	int n;
	cin >> n;
	int d = sum(n);
	cout << d << endl;
    
    return 0;
}

6.3 函数值传递

#include<iostream>
using namespace std;

//函数值传递的本质是参数的复制,并不改变原参数
void swap(int a, int b) {
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "---" << endl;
    
	int tmp = a;
	a = b;
	b = tmp;
    //值交换
    
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "---" << endl;
}


int main(){
    
    int a = 6;
	int b = 9;
	swap(a, b);
	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
    //a,b值不变
    
    return 0;
}

6.4 函数的声明

C++语言中程序执行按照从上到下的顺序执行,必须要先写函数的声明再写函数体才不会报错。

#include<iostream>
using namespace std;

int add(int, int);
void func2(int);
//可以先声明函数

void func1(int x) {
	if (x <= 0) {
		return;
	}
	cout << "func1: " << x << endl;
	func2(x-1);
}

void func2(int x) {
	cout << "func2: " << x << endl;
	func1(x-1);
}

int main() {
	int x, y;
	cin >> x >> y;
	int z = add(x, y);
	cout << z << endl;

	func1(10);
	return 0;
}


7. 指针和地址

7.1 指针的概念


0X4B32F824|0X4B32F825|0X4B32F826|…|…|…|…|…| 内存地址
11 9 变量值

  a           b                                                        变量名

char a = 10;
char b = 5;
a = 11;
b = 9;

此时a的内存地址为0X4B32F824,变量值为11,b的内存地址为0X4B32F825,变量值为9


0x00000010|0x00000011|0x00000012|0x00000013| 内存地址
0X4B32F824 变量值
pa 变量名

而定义一个变量pa,使其变量值为变量a的内存地址,且变量pa有属于自己的内存地址,则此时pa为指针。

#include <iostream>

using namespace std;

int main() {

    //简单一句话:指针就是存储地址的变量
    
    return 0;
}


7.2 指针的定义

#include <iostream>

using namespace std;

int main() {
    int a = 10;
    int b = 20
        
//&表地址,*表数值    
        
// 1. 指针变量的定义
    // 数据类型 * 指针变量名;
    int *pa;
    pa = &a;
    // pa = &b;定义指针并指向变量

    printf("%#X %#X\n", &a, pa);//输出地址
    
// 2. 解引用
    // *指针变量名 = 数值;
    *pa = 7;
    cout << a << ' ' << (*pa) << endl;
    cout << "-------" << endl;

// 3. * 和 &
    // *&a = *(&a) = *pa = a;
    // &*pa = &(*pa) = &a = pa;
    cout << (*&a) << endl;
    cout << (*(&a)) << endl;
    cout << (*pa) << endl;
    cout << (a) << endl;
    cout << "-------" << endl;
    cout << (&*pa) << endl;
    cout << (&(*pa)) << endl;
    cout << (&a) << endl;
    cout << (pa) << endl;

    return 0;
}


7.3 指针的内存空间

#include <iostream>

using namespace std;

int main() {
    
    //利用sizeof()函数
	cout << sizeof(int*) << endl;
	cout << sizeof(short*) << endl;
	cout << sizeof(char*) << endl;
	cout << sizeof(long*) << endl;
	cout << sizeof(long long*) << endl;
	cout << sizeof(double*) << endl;
	cout << sizeof(float*) << endl;

	return 0;
}

7.4 空指针和野指针

#include <iostream>
using namespace std;

int main() {
	// 1. 空指针
	int* p = NULL;
	cout << *p << endl;
    //p存储空地址
    

	// 2. 野指针
	p = (int *)0x121412;
	cout << *p << endl;
    //p存储随便地址
    

	return 0;
}

7.5 指针与常量

7.5.1 指针常量

#include <iostream>

using namespace std;

/*
 
 const 和 指针的关系
 
 const int a = 1;
 //定义常量
*/

int main() {
    int a = 1;
    int b = 2;
    
    // 指针常量
    // 指针的值是一个常量,指针指向不可改变
    int* const p = &a;
    // p = &b;   错误
    *p = 6;
    cout << "a = " << a << endl;
    
    int a=10;
	int * const p =&a;  //定义指针常量,指向int a的地址

	*p = 20; //正确,指向的内存地址中的数据可以修改   
 
	p=&b;  //错误,指向的内存地址不可以修改

    

    return 0;
}

7.5.2 常量指针

#include <iostream>

using namespace std;

int main() {
    int a = 1;
    int b = 2;
    // 常量指针
    // 指向常量的指针
    //特点: 指针的指向可以修改,但是指针指向的值不可以修改。
	//常量指针,首先要是常量。就是指向的值要是一个常量,但是指向的内存地址不做限制
    const int* p = &a;
    // *p = 6; 错误
    p = &b;
    cout << "p = " << *p << endl;

    return 0;
}

7.5.3 常量指针常量

#include <iostream>

using namespace std;

/*
指针常量          tpye* const        指针值是一个常量                指针无法被赋值
常量指针          const type*        指向常量的指针                  指针解引用后无法被赋值
常量指针常量      const type* const  指针值和指针指向的值都是常量    指针和解引用都无法被赋值
*/

int main() {
    int a = 1;
    int b = 2;
    // 常量指针常量
    const int* const p = &a;
    // *p = 6;  错误
    // p = &b;  错误

    return 0;
}


7.6 指针和数组

7.6.1 指针和数组

#include <iostream>

using namespace std;


int main() {
    // 1、利用指针来访问数组元素
    int a[5] = { 5,4,3,2,1 };
   
    cout << "数组第一个元素:" << a[0] << endl;
    int* p = a;   // a 代表数组的首地址
    cout << "数组元素首地址:" << a << endl;
    cout << "指针指向的地址为数组元素首地址:" << p << endl;
    cout << "指针访问:数组的第一个元素" << *p << endl;

    
    
    cout << "数组第二个元素的地址:" << &a[1] << endl;
    cout << "指针 + 1  指向的地址为数组第二个元素的地址:" << p + 1 << endl;
    cout << "指针访问数组第二个元素:" << *(p + 1) << endl;

    cout << "数组第三个元素的地址:" << &a[2] << endl;
    cout << "指针 + 2  指向的地址:" << p + 2 << endl;
    cout << "指针访问数组第三个元素:" << *(p + 2) << endl;

    p++;
    cout << "指针访问:数组第二个元素: " << *p << endl;



    p = a;
    for (int i = 0; i < 5; ++i) {
        cout << "数组的第" << (i + 1) << "个元素是" << *p << endl;
        p++;
    }

    double b[4] = { 4,3,2,1 };
    double* pd = b;
    cout << "第一个元素的地址:" << pd << endl;
    pd++;
    cout << "第二个元素的地址:" << pd << endl;

    // 指针的+1,实际上是偏移了 sizeof(对应的指针类型) 个字节
    // char、short、long long、float 
    return 0;
}

7.6.2 指针数组

#include <iostream>

using namespace std;

int main() {
    char a[] = "I";
    char b[] = "love";
    char c[] = "you";
    
    // 指针数组
    //定义为:int* p[n]; (注意优先级:()>[]> *)
	//[]> * ,所以p是数组,是一个由n个指针类型元素组成的指针数组,或者说这个当一个数组里含有的元素为指针类型的时候,它就被成为指针数组。当p+1时,则p指向下一个数组元素。
    
    char* p[3];
    p[0] = a;
    p[1] = b;
    p[2] = c;
    for (int i = 0; i < 3; ++i) {
        cout << p[i] << ' ';
    }
    cout << endl;

    
    
    /*
    下面这段代码演示了如何使用指针数组来访问一个二维数组。逐步解释这段代码的执行过程:

	int mat[3][4]:这定义了一个3行4列的二维整型数组mat,并初始化了数组的值。
	int* pmat[3]:这定义了一个指针数组pmat,其中每个元素都是指向整型数据的指针。
	pmat[0] = mat[0]、pmat[1] = mat[1]、pmat[2] = mat[2]:这三行将二维数组mat每行的起始地址赋给指针数组pmat的对应元素,因此pmat[0]指向mat的第一行,pmat[1]指向第二行,pmat[2]指向第三行。
	for 循环:这是一个嵌套的循环,外层循环遍历指针数组pmat,内层循环遍历每个行的元素。
	cout << *(pmat[i] + j) << ' ';:这里使用指针算术来访问二维数组的元素。pmat[i]是一个指向一维数组的指针,加上j实际上是在移动这个指针,以访问一维数组的不同元素。然后使用间接访问运算符*来获取指针指向的值,并输出到控制台。
	cout << endl;:在内层循环结束后,输出换行符,以便在每行输出结束时换行。
这样,代码将逐行打印二维数组mat的元素。
    
    */
    int mat[3][4] = {
        {1,2,3,4},
        {5,6,7,8},
        {9,10,11,12}
    };
    int* pmat[3];
    pmat[0] = mat[0];
    pmat[1] = mat[1];
    pmat[2] = mat[2];
    for (int i = 0; i < 3; ++i) {
        for (int j = 0; j < 4; ++j) {
            cout << *(pmat[i] + j) << ' ';
        }
        cout << endl;
    }



    return 0;
}

7.6.3 数组指针

#include <iostream>

using namespace std;

int main() {
    int(*p)[5];
    //()优先级高,说明p是指针,指向一个整型的一维数组。这个一维数组的长度是n,也可以说p的步长为n。当p+1时,p指针会跨过n个整型数据的长度。
    //数组指针也成为指向一维数组的指针,也就是行指针。
    
    int a[4][5] = {
        {4,3,2,1,0},
        {9,8,7,6,5},
        {6,7,8,9,0},
        {5,6,7,8,9}
    };
    p = a;               
    cout << p << endl;      
    //p=a;   将二维数组的首地址赋值给p,也可是a[0]或&a[0][0]
    
    cout << p + 1 << endl;  
    //p++;           //表示p跨过行a[0][],指向了行a[1][]

    cout << p << ':' << &a[0] << endl;
    cout << p + 1 << ':' << &a[1] << endl;

  

    return 0;
}

7.7 函数传参

7.7.1 指针传参

#include <iostream>
using namespace std;

// 函数的址传递
void swap(int* a, int* b) {
    cout << "调用函数后 a 的地址 = " << a << endl;
    cout << "调用函数后 b 的地址 = " << b << endl;
    cout << "----------------" << endl;
    int temp = *a;
    cout << "调用函数后 a 的值 = " << *a << endl;
    cout << "调用函数后 b 的值 = " << *b << endl;
    cout << "调用函数temp 的值 = " << temp << endl;
    cout << "----------------" << endl;
    *a = *b;
    cout << "调用函数后 a 的值 = " << *a << endl;
    cout << "调用函数后 b 的值 = " << *b << endl;
    cout << "调用函数temp 的值 = " << temp << endl;
    cout << "----------------" << endl;
    *b = temp;
    cout << "调用函数后 a 的值 = " << *a << endl;
    cout << "调用函数后 b 的值 = " << *b << endl;
    cout << "调用函数temp 的值 = " << temp << endl;
    cout << "----------------" << endl;
}

int main() {
    int a = 1;
    int b = 2;
    cout << "调用函数前 a 的地址 = " << &a << endl;
    cout << "调用函数前 b 的地址 = " << &b << endl;
    swap(&a, &b);
    cout << "a = " << a << endl;
    cout << "b = " << b << endl;
    cout << "----------------" << endl;
    return 0;
}

7.7.2 指针函数

#include <iostream>
using namespace std;

// 指针函数
//指的是函数的返回值是一个指针,比如我的函数返回的是一个指向整数int的指针,定义格式如下:

int* func() {
    return NULL;
}

int* getArray(int a, int d, int n) {
    int* ret = new int[n];
    // ret[0] = a;
    // ret[1] = a + d;
    // ...
    // ret[i] = a + i * d;
    for (int i = 0; i < n; ++i) {
        ret[i] = a + i * d;
    }
    return ret;
}
//int* ret = new int[n];:在函数内部,代码使用new操作符动态分配了一个长度为n的整型数组,并将指向这个数组的指针存储在ret中。
//for 循环:在循环中,从0到n-1遍历数组的每个元素,计算并存储等差数列的值,公式为a + i * d,其中i表示当前的索引。
//ret[i] = a + i * d;:在循环中,将计算得到的等差数列的值存储在数组ret的相应位置。
//return ret;:最后,函数返回指向动态分配数组的指针ret。这意味着调用方将获得一个指向包含等差数列值的数组的指针。

//在这段代码中,数组ret是通过使用new操作符在堆(heap)上动态分配的。具体来说,new int[n]这个表达式会在运行时分配一个长度为n的整型数组,并返回数组的首地址。这个地址被存储在指针ret中。



int main() {
    int* ans = getArray(5, 3, 6);
    //ans是指向动态分配数组的指针
    
    for (int i = 0; i < 6; ++i) {
        cout << *(ans + i) << endl;
    }
    for (int i = 0; i < 6; ++i) {
        cout << ans[i] << endl;
    }
    //通过ans[i]直接访问数组中的元素
    
    return 0;
}

7.7.3 函数指针

#include <iostream>
using namespace std;

// 函数指针
//定义一个指向函数的指针变量

double (*ptr)(int a, int b, int c);
定义一个与func兼容的指针

void (*ptr1)(int a, int b);

double func(int a, int b, int c) {
    cout << a << "," << b << "," << c << endl;
    return 0.0;
}

void func1(int a, int b) {
    cout << a << "," << b << endl;
}

int main() {
    ptr = func;
    //通过指针调用
    ptr(4, 5, 6);
    
    // ptr = func1; 错误
    ptr1 = func1;
    ptr1(5, 6);

    return 0;
}

7.7.4 函数指针的类型定义

#include <iostream>
using namespace std;
//以下代码展示了函数指针的定义和使用,以及函数指针类型的简化声明
//void (*fptr1) (int a, int b, int c, float d, char e); 和 void (*fptr2) (int a, int b, int c, float d, char e);:这里定义了两个函数指针 fptr1 和 fptr2,它们都指向函数,该函数接受一个整型参数 a,两个整型参数 b 和 c,一个浮点数参数 d,以及一个字符参数 e。
//void func1(int a, int b, int c, float d, char e):这是一个函数 func1 的定义,打印了 "func1"。
//typedef void (*fptr) (int a, int b, int c, float d, char e);:这里定义了一个函数指针类型 fptr,简化了函数指针的声明。
//fptr1 = func1; 和 fptr2 = func1;:将函数 func1 的地址分别赋给 fptr1 和 fptr2,这样,fptr1 和 fptr2 现在指向了 func1 函数。
//fptr1(1, 2, 3, 4, 5);:通过 fptr1 调用函数 func1,传递参数 1, 2, 3, 4, 5。
//fptr2(9, 8, 7, 6, 5);:通过 fptr2 调用函数 func1,传递参数 9, 8, 7, 6, 5。
//fptr fp1 = func1;:定义了一个新的函数指针 fp1,并将其指向 func1 函数。
//fp1(7, 6, 5, 4, 3);:通过 fp1 调用函数 func1,传递参数 7, 6, 5, 4, 3。





// 函数指针的定义
void (*fptr1) (int a, int b, int c, float d, char e);
void (*fptr2) (int a, int b, int c, float d, char e);

void func1(int a, int b, int c, float d, char e) {
    cout << "func1" << endl;
}

// 函数指针的类型定义
typedef void (*fptr) (int a, int b, int c, float d, char e);

int main() {
    fptr1 = func1;
    fptr1(1, 2, 3, 4, 5);

    fptr2 = func1;
    fptr2(9, 8, 7, 6, 5);

    fptr fp1 = func1;
    //int  x = 6;
    fp1(7, 6, 5, 4, 3);

    return 0;
}

7.7.5 函数指针数组

#include <iostream>
using namespace std;

// 函数指针数组
// [函数指针1, 函数指针2, ... ]

//typedef void (*fptr) (int a, int b, double c, float d, char e);:定义了一个函数指针类型 fptr,指向一个函数,该函数接受参数 (int, int, double, float, char) 并返回 void。

//typedef void (*fptrs[56]) (int a, int b, double c, float d, char e);:定义了一个包含 56 个元素的函数指针数组类型 fptrs,每个元素都是一个指向函数的函数指针。

//void func1(int a, int b, double c, float d, char e)、void func2(int a, int b, double c, float d, char e)、void func3(int a, int b, double c, float d, char e):这些函数分别打印 "func1"、"func2" 和 "func3"。

//fptrs fps = {func1, func2, func3};:定义了一个函数指针数组 fps,包含指向 func1、func2 和 func3 函数的函数指针。fps 是一个函数指针数组,它被定义为 typedef void (*fptrs[56]) (int a, int b, double c, float d, char e);,因此 fps 是一个包含 56 个函数指针的数组。

//cout << fps[0] << endl;、cout << fps[1] << endl;、cout << fps[2] << endl;、cout << fps[3] << endl;:尝试打印函数指针数组 fps 的元素,但这里可能会输出函数指针的地址,而不是函数名。

//fptr fp[] = { func1, func2, func3 };:定义了一个函数指针数组 fp,包含指向 func1、func2 和 func3 函数的函数指针。

//cout << fp[0] << endl;、cout << fp[1] << endl;、cout << fp[2] << endl;:尝试打印函数指针数组 fp 的元素,同样可能会输出函数指针的地址。

//在 C++ 中,直接打印函数指针可能会输出函数指针的地址,而不是函数名。如果需要调用函数指针指向的函数,应该使用函数指针来调用相应的函数。





typedef void (*fptr) (int a, int b, double c, float d, char e);
typedef void (*fptrs[56]) (int a, int b, double c, float d, char e);

void func1(int a, int b, double c, float d, char e) {
    cout << "func1" << endl;
}
void func2(int a, int b, double c, float d, char e) {
    cout << "func2" << endl;
}
void func3(int a, int b, double c, float d, char e) {
    cout << "func3" << endl;
}


int main() {
    //int  a[]= {1 ,2, 3 };
    fptrs fps = {func1, func2, func3};
    cout << fps[0] << endl;
    cout << fps[1] << endl;
    cout << fps[2] << endl;
    cout << fps[3] << endl;

    fptr fp[] = { func1, func2, func3 };
    cout << fp[0] << endl;
    cout << fp[1] << endl;
    cout << fp[2] << endl;

    return 0;
}

8. 结构体

8.1 结构体的定义

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

// 1. 结构体定义
// struct 结构体名 { 结构体成员变量列表 };
struct Book {
	string name;
	double price;
	int value;
}cpp;

// 2. 创建结构体

int main() {
	// 2.1 
	Book c;
	c.name = "C语言程序设计";
	c.price = 39.99;
	c.value = 10;
	cout << c.name << ' ' << c.price << ' ' << c.value << endl;
	
	// 2.2
	Book py = { "Python编程", 1999, 10 };
	cout << py.name << ' ' << py.price << ' ' << py.value << endl;

	// 2.3 
	cpp.name = "C++零基础编程";
	cpp.price = 9999999;
	cpp.value = 10000000;
	cout << cpp.name << ' ' << cpp.price << ' ' << cpp.value << endl;

	return 0;
}

8.2 结构体数组

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

// 1. 结构体定义
// struct 结构体名 { 结构体成员变量列表 };
struct Book {
	string name;
	double price;
	int value;
}cpp;

int main() {
	// 2. 创建一个结构体数组
	// Book 数组名[元素个数] = { {}, {}, {}, ... };
	Book books[3] = {
		{"C语言程序设计", 199.99, 7},
		{"Python零基础", 399.99, 9},
		{"C++零基础", 39.99, 1000000}
	};
	books[2].name = "C++入门到入土!";
	for (int i = 0; i < 3; ++i) {
		cout << books[i].name << ' ' << books[i].price << ' ' << books[i].value << endl;
	}

	return 0;
}

8.3 结构体指针

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

// 1. 结构体定义
// struct 结构体名 { 结构体成员变量列表 };
struct Book {
	string name;
	double price;
	int value;
};

int main() {
	Book b = {"C语言", 99.99, 7};
	Book c = b;
    //b将自身信息赋值给c
	c.name = "C语言入门";
    
	//结构体名* 指针名 = &结构体变量名;
    Book* pb = &b;
	pb->name = "C++";
    //用->
	cout << b.name << ' ' << b.price << ' ' << b.value << endl;

	return 0;
}

8.4 嵌套结构体

#include <iostream>

using namespace std;


//这段 C++ 代码创建了三结构体 Point, Circle, 和 Circles,并在 main 函数中演示了它们的用法。

//Point 结构体表示一个二维点,具有 x 和 y 坐标。
//Circle 结构体表示一个圆,包含一个中心点 pt 和半径 radius。
//Circles 结构体包含一个整数 size 和一个固定大小为100的 Circle 数组 c。
//在 main 函数中:

//创建一个 Circle 结构体 c,设置其中心点坐标和半径。
//创建一个 Circles 结构体 cs,初始化其大小为 2,包含两个圆的信息。
//使用循环遍历 cs 结构体中的圆数组,打印每个圆的中心点坐标和半径。



struct Point {
    double x, y;
};

struct Circle {
    Point pt;
    double radius;
};

struct Circles {
    int size;
    Circle c[100];
};


int main() {
    Circle c;
    c.pt.x = 9;
    c.pt.y = 8;
    c.radius = 5;

    Circles cs = {
        2, {
            { {9,8}, 5 },
            { {2,1}, 1 }
        }
    };
    //Circles cs 是一个 Circles 结构体类型的变量,初始化包括两个部分:
		//2:这是 Circles 结构体中的整数成员 size 的初始值,表示这个 Circles 结构体中包含的圆的数量为 2。
		//{{9, 8}, 5}, {{2, 1}, 1}:这部分初始化了 Circle 结构体数组 c。其中,{9, 8} 和 5 初始化了第一个圆的中心坐标和半径,{2, 1} 和 1 初始化了第二个圆的中心坐标和半径。
    
    
    for (int i = 0; i < cs.size; ++i) {
        Circle tmp = cs.c[i];
        cout << "(" << tmp.pt.x << "," << tmp.pt.y << ") " << tmp.radius << endl;
    }

    return 0;
}

8.5 结构体传参

#include <iostream>
using namespace std;

struct Point {
    double x, y;
};

struct Circle {
    Point pt;
    double radius;
};

void printCircle(const Circle *c) {
    //printCircle 函数被声明为接受指向 const Circle 的常量指针作为参数。这意味着在函数体内部,你不能修改指针指向的内容,因为该内容被视为常量。

//在函数内部,你尝试修改 c 指向的圆的中心点坐标 x 的值,但是由于 c 是一个指向 const Circle 的常量指针,所以任何尝试修改指针指向的数据都会导致编译错误。

//在代码中,你注释掉了 c->pt.x += 1; 这行代码,这是正确的做法,因为在 printCircle 函数中,应该避免修改通过常量指针传递的对象的内容。

//因此,printCircle 函数的目的是打印圆的信息而不是修改圆的内容。通过使用常量指针作为参数,可以确保在函数内部不会意外地修改传递进来的数据。
    
    
    // c->pt.x += 1; 常量不可修改
    cout << "(" << c->pt.x << "," << c->pt.y << ") " << c->radius << endl;
}

void moveCircle(Circle *c, int x, int y) {
    //cout << &c << endl;
    c->pt.x += x;
    c->pt.y += y;
}

int main() {
    Circle c = { {9,8}, 5 };
    //cout << &c << endl;
    moveCircle(&c, 1, -2);
    printCircle(&c);
    return 0;
}

  • 19
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值