CSP初赛复习-13-C++语言基础-进阶

变量

变量代表内存中具有特定属性的一个存储单元。它是一个地址和一个值的统称

地址

C语言地址,是指内存地址的概念。计算机内存中的各个存储单元都是有序的,按字节编码

每个字节有一个唯一的编码

变量地址

获取变量地址,使用&

示例

#include <iostream>
using namespace std;
int main(){
	int a=5;
	cout<<&a<<endl;
	float b=4.15;
	cout<<&b;		
}
/*
输出结果 
0x70fe1c
0x70fe18
*/

数组变量地址

数组中的变量是相同类型

数组中的变量按顺序存储,数组中的变量和地址就有了相应的对应关系

比如:

int a[5]={1,2,3,4,5};

&a[0]=0x70fe00则 &a[1]=0x70fe04

因为a是整形,a[0]占4个字节,对应占用4个地址

示例

#include <iostream>
using namespace std;
int main(){
	//a数组是int类型,数组中每个元素占4个字节
	//数组顺序存储,&a[1]=&a[0]+4; &a[0]=0x70fe00则 &a[1]=0x70fe04 
	int a[5]={1,2,3,4,5}; 
	for(int i=0;i<5;i++){
		cout<<&a[i]<<endl;
	}	
}
/*
输出结果 
0x70fe00
0x70fe04
0x70fe08
0x70fe0c
0x70fe10
*/

指针与数组

1 数组名是数组首元素的地址

#include <iostream>
using namespace std;
int main(){
	int a[5]={1,2,3,4,5}; 
	cout<<&a<<endl;
	cout<<&a[0];//这2个地址相同
}
/*
输出结果 
0x70fe00
0x70fe00
*/

2 地址运算

地址+1,相当于+本数据类型的字节数

比如 int类型,+1相当于+4

#include <iostream>
using namespace std;
int main(){
	int a[5]={1,2,3,4,5}; 
	cout<<&a<<endl;//0x70fe00
	cout<<a+1<<endl;//0x70fe04 -int类型变量,占4个字节,所以地址变量+1,实际+4
	
	long long b[5]={1,2,3,4,5}; 
	cout<<&b<<endl;//0x70fdd0
	cout<<b+1<<endl;//0x70fdd8 -long long类型变量,占8个字节,所以地址变量+1,实际+8
}
/*
输出结果 
0x70fe00
0x70fe04
0x70fdd0
0x70fdd8
*/

3 指针数组

1 使用指针访问数组元素

通过改变指针遍历的地址,遍历地址对应的数组元素

#include <iostream>
using namespace std;
int main(){
	int a[5]={1,3,5,7,9}; 
	int *p;//声明指针变量 p 
	p=a;//把a数组首元素地址赋值给指针p 
	cout<<p<<" "<<*p<<endl;//输出指针p对应地址的值 
	cout<<p+1<<" "<<*(p+1);//输出指针p对应地址下一个元素地址的值 
}
/*
输出结果
0x70fdf0 1
0x70fdf4 3
*/

2 使用指针遍历数组

通过指针遍历数组元素地址的值

#include <iostream>
using namespace std;
int main(){
	int a[5]={1,3,5,7,9}; 
	int *p;//声明指针变量 p 
	p=a;//把a数组首元素地址赋值给指针p 
	for(int i=0;i<5;i++){
		cout<<*(p+i)<<endl;//根据首地址每次加1 2 3 对应地址加4 8 12 
	} 
}
/*
输出结果
1
3
5
7
9
*/

3 指针数组

声明指针数组int (*p)[5]; 指向对应数组中对应元素的地址

#include <iostream>
using namespace std;
int main(){
	int a[5]={1,3,5,7,9}; 
	int (*p)[5];//声明指针数组p 里面包括5个指针变量 
	p=&a;//把a数组赋值指针数组 
	for(int i=0;i<5;i++){
		cout<<(*p)[i]<<endl;//取出对应指针数组地址的值 
	} 
}
/*
输出结果
1
3
5
7
9
*/

4 指针访问二维数组

指向元素的指针,指向二维数组首地址

int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
int *p=&a[0][0];

使用指针遍历二维数组

#include <iostream>
using namespace std;
int main(){
	int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
	int *p=&a[0][0];
	for(int i=0;i<3;i++){
		for(int j=0;j<4;j++){
			printf("%2d  ",*(p+i*4+j));
		}
		printf("\n"); 
	}
}
/*
输出结果 
 1   2   3   4
 5   6   7   8
 9  10  11  12
*/

使用指针数组遍历二维数组

#include <stdio.h>
int main(){
    int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};
    int(*p)[4];//指针数组临时变量 表示一行 
    int i,j;
    p=a;
    for(i=0; i<3; i++){
    	//*(p+i)取出每行的首地址 
    	//*(p+i)+j 每行在首地址基础上到第几列 
        for(j=0; j<4; j++) printf("%2d  ",*(*(p+i)+j));
        printf("\n");
    }
    return 0;
}
/*
输出结果
 0   1   2   3
 4   5   6   7
 8   9  10  11
*/

函数

C++ 中的函数由一段相对独立的代码组成,这段代码能实现某一项具体、独立、完整的功能

函数在程序设计中的作用主要有两个,一是“代码重用”;二是“问题分解”

1 函数的定义

数据类型 函数名(形式参数表)
{
    //函数体执行语句 
    ... 
}
int max2(int x, int y) 
{
    //函数体执行语句 
    return (x > y) ? x : y; 
}

2 函数的调用

函数名(实参列表) 
max2(5,9);

3 示例

#include<iostream> 
using namespace std; 
int max2(int x, int y){ 
	return (x > y) ? x : y; 
} 
int main(){ 
	int a = max2(10, -1); 
	cout<<a<<endl; 
	return 0; 
} 
/*
输出结果
10
*/

指针与函数

1 函数内部指针变量指向地址交换,对main函数变量无影响

#include<stdio.h>
void fun( int *a, int *b ){
	int *k;//临时指针变量 
	//交换函数局部变量a b对应地址 对fun函数外无影响 
	k = a; a = b; b = k;
}

int main(){
	int a = 3, b = 6, *x = &a, *y = &b;
	fun( x, y );
	printf( "%d,%d ", a, b );
}
/*
输出结果
3,6
*/

2 传地址和传指针都可以

#include <stdio.h>
void fun( int *a, int *b ){
	int *k;
	//交换函数局部变量a b对应地址 对fun函数外无影响 
	k = a; a = b; b = k;
} 
main(){
	int a = 3, b = 6, *x = &a, *y = &b;
	fun( x, y );//可以传指针  指针指向地址 
	printf( "No.1: %d,%d ", a, b );
	fun( &a, &b );//可以传地址 传地址和传指针效果一样 
	printf( "No.2: %d,%d\n", a, b );
}
/*
输出结果
No.1: 3,6 No.2: 3,6
*/

3 通过指针交换变量的值

#include <stdio.h>
void fun(int* px, int* py) {
	int tmp = 0;
	//交换指针指向变量的值 即 交换里main函数 num1 num2的值 
	tmp = *px;
	*px = *py;
	*py = tmp;
}
int main(){
	int num1 = 1;
	int num2 = 2;
	fun(&num1, &num2);
	printf("num1 = %d num2 = %d\n", num1, num2);
	return 0;
}
/*
输出结果
num1 = 2 num2 = 1
*/

引用的概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,

它和它引用的变量共用同一块内存空间

1 修改引用变量 变量都修改

#include <iostream>
using namespace std;
int main(){
	int a=10;
	int& b=a;//给变量a起一个别名 叫b
	cout<<"a= "<<a<<endl;
	cout<<"b= "<<b<<endl;
	b=20;//修改了b 则a和b都修改了 
	cout<<"a= "<<a<<endl;
	cout<<"b= "<<b<<endl;
	return 0;
}
/*
输出结果
a= 10
b= 10
a= 20
b= 20
*/

2 引用做函数参数 -外部变量也被修改

#include <iostream>
using namespace std;
void fun(int & a, int & b){
    int t;
    t = a;
    a = b;
    b = t;
}
int main(){
	int a=3,b=5;
    fun(a,b);//引用是同一个 直接交换了a b的值 
    cout<<"a="<<a<<" b= "<<b;
    return 0;
}
/*
输出结果
a=5 b= 3
*/

递归函数

递归是返回调用自身函数,一个函数在它的函数体内调用它自身称为递归调用

每次把问题范围缩小,直到范围缩小到可以直接得到边界数据的结果,

然后根据已计算的结果再返回路上求出对应的解

1 递归重要概念

递归式-递归函数

将原问题分为若干规模较小、相互独立、与原问题形式相同或相似的子问题

比如:斐波那契数列

由上可知递归式为:F(1)=1,F(2)=1, F(n)=F(n - 1)+F(n - 2)

递归边界

递归边界则是分解的尽头,如果递归式不断递归而不进行阻止,那么最后将进入无穷尽的死循环,将无法解

决问题

2 经典示例

问题1

使用递归求解n的阶乘

分析

n!= 123…n

n!= (n-1)!*n

于是就把规模为n的问题转化为求解规模为n-1的问题了

由上可知:每一项是上一项结果*当前项

递归式为:F(n) = F(n-1)*n

递归边界:

由于 0!=1 因此不妨以F(0)=1作为递归边界

示例代码

执行过程

问题2

求斐波那契数列的第n项

分析

F(n)=F(n - 1)+F(n - 2)

把规模为n的问题转化为求解规模为n-1和n-2和

由上可知:从第三项开始,当前项为前两项之和

递归式为: F(n)=F(n - 1)+F(n - 2)

递归边界:

由于从第三项开始,当前项为前两项之和,因此F(1)=1和F(2)=1作为递归边界

示例代码

执行过程

CSP初赛复习-13-C++语言基础-练习题
https://www.cnblogs.com/myeln/articles/17564414.html

posted @ 2023-07-18 23:11  new-code  阅读(54)  评论(0)    收藏  举报