c++入门基础二

函数进阶

//函数在执行时,可能会影响调用者
/*被调方(callee)如何影响主调方(caller)
1 返回值
2 指针参数
3 形参是:指针的指针
4 形参是:引用*/

/*指针形参
这种方式,好比调用方准备了一个盒子,把盒子地址传过去,被调
方往里塞东西*/
# include <iostream>  // 标准输入输出流  input输入  output输出
using namespace std; // 使用标准 命名空间
void swap(int* a, int* b) // 用来交换俩个变量的值
{
    int t = *a;
    *a = *b;
    *b = t;
}
// 对数据进行排序 采用的是冒泡排序的方法
void bubble_sort(int* a, const int N) 
{
    for(int j = 0; j < N-1; j++){
        for(int i = 0; i < N-j-1; i++){
            if(a[i] > a[i+1])
               swap(a[i], a[i+1]);
       }
   }
}
// 主函数入口
int main(){
    int a[] = {3,5,9,2,7,8,1,4,6};
    bubble_sort(a, sizeof(a) / sizeof(int));
    for(int i = 0; i < sizeof(a) / sizeof(int); i++)
        cout << a[i] << " ";
    return 0;
}

数组与指针进阶

// 通过以下代码输出了解数组的本质
int a[3] = {1, 2, 3};
int b[3] = {1, 2, 3};
int* p = a;
cout << (a == b) << endl; // == 的含义?
cout << a << endl;
cout << b << endl;
cout << p << endl;
a = b;  //编译不过去!
cout << sizeof(a) << "," << sizeof(p) << endl;

// p + n 真实的增量是 n * sizeof(单个元素) 比如int就是 n * 4
int a;
int* p = &a;
cout << p << endl;
p++;
cout << p << endl;

// 指针运算与[ ]运算的等效性
*(p + n) === p[n] // === 全等
*p === p[0]
    
// 指针与数组可以通用
    
//拓展:数组引用(用作参数的时候,有区别)
//作为形式参数时:
int (&p)[3]  //携带了长度信息
int p[3], int p[], int* p //是等同的  

二维数组

// 填充数组
int a[3][6];
int *p = &a[0][0];  // == &(a[0][0])
for(int i=0; i < sizeof(a)/sizeof(int); i++)
{
    p[i] = i+1;
}
for(int i = 0; i < 3; i++)
{
    for(int j = 0; j < 6; j++)
    {
        cout << a[i][j] << " ";
    }
    cout << endl;
}

动态内存分配

内存的分配与释放

1、栈空间(stack)的分配与释放是自动进行的,是隐式

2、堆空间(heap)的分配与释放是代码显式操作行为

使用方法

// 判断一个数是否是素数 返回bool类型
boolis_prime(int x)
{
    for(int i=2; i<x; i++)
    {
     if(x%i==0)
            return false;
    }
    return true;
}

指针数组与数组指针

指针数组

指针数组是一个数组,它的每个元素都是指针,这个指针可以是任何类型

当然,也可以是指向另一个数组的指针(可以仿造出类似java中的不等长数组)

int*p[9];  // p 是含有9个元素的数组,每个元素类型为 int*
p[0] =new int[1]; // 第一个指针指向:一个元素的数组
p[1] =new int[2]; // 第二个指针指向:二个元素的数组

数组指针

数组指针是一个指针,它指向一个数组。在32 位系统下任何类型的指针永远是占4 个字节,至于它指向的数组占多少字节,不知道,具体要看数组大小

//n 是二维数组的高度信息,宽度信息在指针类型中携带了
void f(int (*p)[3], int n)  
{
    for(int i=0; i<n; i++){
        p[i][0] *= p[i][0];
   }
}
// 调用方
int main{
    int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
    f(a,3);
    cout << a[2][0]; // 49
}

const,break,continue,return的使用

// const
const int a[] = {5};  //修饰的是 int
int const b[] = {6};  //同上,修饰 int
b[0]++;  //会被编译器阻止

int x = 5;
const int * p = &x;   //修饰int, 元素不能变,也就是保护x
int * const r = &x;   //修饰的是指针,r将来不能指向别人,但x可以改

//修饰的目的是为了防止数据被意外修改


/*
break,continue,return
它们都是流程控制的语句,还有goto
break, continue, 只能作用于最内层的循环(break还可以跳出switch分支)
return 可以跳出多层循环
*/

// 输出100以内的素数
bool is_prime(int x)
{
    for(int i=2; i<x; i++)
    {
     if(x%i==0)
        return false;
    }
    return true;
}

int main(){
    for(int n=2; n<100; n++)
    {
        if(is_prime(n)) cout << n << " ";
    }
    cout << endl;
    return 0;
}

数学运算

c 的传统是包含 math.h ,c++是完全兼容 c 的,这个当然可以

c++的标准写法是包含 cmath (注意,没有.h),这个与math.h基本相同

/*rand() 产生 0 ~ RAND_MAX 之间的一个伪随机整数
这个序列每次都一样,这样==方便测试==
当需要不一样的时候,可以用初始化==随机种子==
srand(time(NULL))*/

按位运算

//有符号和无符号的区别
char a=0xff;
a>>=1;  // 此时 a 内值为: 0xff
unsigned char b=0xff;
b>>=1;  // 此时 b 内值为: 0x7f

数据类型转换

c/c++是静态的,弱类型语言

静态类型意味着:

1、变量类型自始至终不变

2、在程序执行前,编译器就知道变量的类型

弱类型

1、相对于强类型而言,弱类型不拘束于类型

2、可以把 A 类型的东西硬当成 B 类型来用(强制转换)

递归入门

递归通俗理解就是:函数自己调用自己

/*1 递归一定要有出口,在某种条件下,不再递归,出口多不怕,怕漏
2 递归有可能很慢,这是因为有重复计算问题,如何避免重复计算? 动态规划或哈希表缓存
3 递归有可能引发 stackoverflower,递归的深度要有个估计*/
// 递归求阶乘
int jiecheng(int x)
{
    if (x == 0) return 0;
    if (x == 1) return 1;
    return x * jiecheng(x-1);
}
// 递归求前n项的和
int my_sum(int x)
{
    if (x < 1) return 0;
    return x + my_sum(x - 1);
}
// 递归求斐波那契数列 1 1 2 3 5 8 13 21.......
int feibonaqie(int a)
{
    if (a == 0) return 0;
    if (a == 1) return 1;
    if (a == 2) return 1;
    return feibonaqie(a - 1) + feibonaqie(a - 2);
}

//递归与循环的关系
//任何循环形式,必然可以使用递归表达/*1 递归一定要有出口,在某种条件下,不再递归,出口多不怕,怕漏
2 递归有可能很慢,这是因为有重复计算问题,如何避免重复计算? 动态规划或哈希表缓存
3 递归有可能引发 stackoverflower,递归的深度要有个估计*/
// 递归求阶乘
int jiecheng(int x)
{
    if (x == 0) return 0;
    if (x == 1) return 1;
    return x * jiecheng(x-1);
}
// 递归求前n项的和
int my_sum(int x)
{
    if (x < 1) return 0;
    return x + my_sum(x - 1);
}
// 递归求斐波那契数列 1 1 2 3 5 8 13 21.......
int feibonaqie(int a)
{
    if (a == 0) return 0;
    if (a == 1) return 1;
    if (a == 2) return 1;
    return feibonaqie(a - 1) + feibonaqie(a - 2);
}

//递归与循环的关系
//任何循环形式,必然可以使用递归表达

函数指针与回调函数

通过函数名,可以调用单个函数,通过函数指针数组,可以调用一组函数

回调函数就是形参是函数指针,函数中,调用这个函数指针的用法

// 通用冒泡排序,可以用户自己传入参数
#include <iostream>
using namespace std;
typedef int ITEM; // 可以换任何用户定义的类型
void swap(ITEM& a, ITEM& b){ ITEM t=a; a=b; b=t;}  // 做变量交换
void bubble_sort(ITEM* buf, int n, int (*fp)(ITEM& a, ITEM& b) )
{
  for(int j=0; j<n-1; j++){
    for(int i=0; i<n-j-1; i++){
      if((*fp)(buf[i],buf[i+1])>0)
        swap(buf[i],buf[i+1]);
     }
   }
}
int f(int&a, int&b)
{
  return a - b;
}
void show(int* buf, int n)
{
  for(int i=0; i<n; i++) cout << buf[i] << " ";
  cout << endl;
}
//主函数入口
int main()
{
  int a[] = {4,17,2,19,9,28,31,22,10};
  bubble_sort(a, 9, f);
  show(a, 9);
}

内存泄漏

堆空间中分配的内存,忘记了回收,或者没有恰当回收,则产生泄漏

解决:自己在申请空间后,自己回收

结构体 联合体

结构体是一种复合类型,也是一种用户定义类型,通俗地说,它捆绑多个变量,使之成为一个整体

联合体也是一种复合结构,用户定义类型,struct 可以看作成员的 与 ,union可以看作成员间 或 的关系,也就是说,union的成员是共享同一块存储的。,各成员所占用的空间可以不等长,整体取最大的。

// 结构体
struct STU2
{
    char* name;
    int age;
};
// 使用:
char name[] = "zhangsan";
STU2 t1 = {name, 15};
STU2 t2 = t1;
cout << sizeof(t1) << endl;  // 8
t1.name[0] = 'X';
cout << t2.name << endl; // Xhangsan

// 联合体
union MyIP{
    unsigned char ipv4[4];  // 4 字节的IP地址
    unsigned char ipv6[6];  // 6 字节的IP地址
};

ps:持续记录学习过程,希望对大家有帮助

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值