知识导图 知识导图
首页
iOS知识
计算机软件
  • 即时通讯网 (opens new window)
  • 开发常用网站 (opens new window)
首页
iOS知识
计算机软件
  • 即时通讯网 (opens new window)
  • 开发常用网站 (opens new window)
  • MD

  • Vue

  • C语法

  • C++语法

    • C++基础概念(上)
    • C++基础概念(下)
      • 循环
        • 循环类型
        • 循环控制语句
        • 无限循环
        • 判断语句
      • 函数
        • 函数声明
        • 定义函数
        • 调用函数
        • 函数参数
        • 函数参数的默认值
        • 数据操作函数
        • 随机数函数
      • 数组
        • 声明数组
        • 初始化数组
        • 访问数组元素
        • 多维数组
        • 初始化多维数组
        • 指向数组的指针
        • 传递数组给函数
        • 函数返回数组
      • 字符串
        • C 字符串
        • C++ 字符串
      • 指针
        • 访问内存地址
        • 指针?
        • 空指针
        • 指针移动
        • 指针和数组
        • 指向指针的指针
        • 函数指针参数
        • 函数返回指针
      • 引用(别名)
        • 引用
        • 引用作为参数
        • 函数中返回引用
      • 流
        • 标准输入输出流
        • 标准错误流(cerr)
        • 标准日志流(clog)
      • 数据结构struct
        • 定义结构
        • 结构的使用
      • typedef (别名)
    • C++语法速查
    • C++面向对象(上)
    • C++面向对象(下)
    • C++高级教程(上)
    • C++高级教程(中)
    • C++高级教程(下)
  • 汇编语言

  • 软件编程及算法
  • C++语法
2023-05-31
目录

C++基础概念(下)

# 循环

在满足条件的情况下重复执行一份代码

# 循环类型

while、for 或 do..while 循环

循环可以嵌套使用

# 循环控制语句

控制语句 描述
break 循环体结束,执行下面代码
continue 当前循环代码结束,执行下一次循环判断
goto 直接跳转到对应的代码执行

# 无限循环

while、for 或 do..while 循环中,如果条件永远不为假,则循环将变成无限循环

#include <iostream>
using namespace std;
 
int main ()
{
    for( ; ; ){
        printf("无限循环.\n");
    }
    return 0;
}

# 判断语句

也就是比较相关

比如:

if - else if

以及三位运行符号:

Exp1 ? Exp2 : Exp3;

# 函数

函数是代码块的复用

包含修饰,返回类型,函数名称,参数 等等

# 函数声明

告诉编译器有这么个函数可以使用:

return_type function_name( parameter list );

# 定义函数

函数具体实现内容

return_type function_name( parameter list )
{
    body of the function
}

# 调用函数

函数调用要根据函数对应作用域来使用,局部还是全局,对象还是类等等

eat();

# 函数参数

默认情况下,C++ 使用传值调用来传递参数

函数传递参数的方式:

参数 描述
传值 对象的数据值作为参数,函数内修改不影响这个对象
指针参数 参数是对象指针,函数内修改后会被影响
引用对象 参数是对象引用,函数内修改后会被影响

# 函数参数的默认值

当您定义一个函数,您可以为参数列表中后边的每一个参数指定默认值。当调用函数时,如果实际参数的值留空,则使用这个默认值。

这是通过在函数定义中使用赋值运算符来为参数赋值的。调用函数时,如果未传递参数的值,则会使用默认值,如果指定了值,则会忽略默认值,使用传递的值。请看下面的实例:

#include <iostream>
using namespace std;
 
int sum(int a=1, int b=2){
    return a + b;
}

int main (){
    int result = sum();
    cout << "默认求和值 :" << result << endl; 

    result = sum(3); 
    cout << "求和值 :" << result << endl;

    result = sum(4, 6); 
    cout << "求和值 :" << result << endl;
    return 0;
} 

结果:

默认求和值 :3
求和值 :5
求和值 :10

# 数据操作函数

常见数据操作库函数:

函数 描述
double cos(double); 该函数返回弧度角(double 型)的余弦。
double sin(double); 该函数返回弧度角(double 型)的正弦。
double tan(double); 该函数返回弧度角(double 型)的正切。
double log(double); 该函数返回参数的自然对数。
double pow(double, double); 则该函数返回 x 的 y 次方。
double hypot(double, double); 该函数返回两个参数的平方总和的平方根
double sqrt(double); 该函数返回参数的平方根。
int abs(int); 该函数返回整数的绝对值。
double fabs(double); 该函数返回任意一个十进制数的绝对值。
double floor(double); 该函数返回一个小于或等于传入参数的最大整数。

# 随机数函数

rand();

#include <iostream>
#include <ctime>
#include <cstdlib>

using namespace std;
 
int main ()
{
    int i,j;

    // 设置种子(生成随机数之前先调用 srand()函数初始化)
    srand( (unsigned)time( NULL ) );

    for( i = 0; i < 3; i++ ){
        // 生成实际的随机数
        j= rand();
        cout <<"随机数: " << j << endl;
    }
    return 0;
} 

# 数组

1、数组存储一个一系列大小的相同类型元素的顺序集合

2、数组中的特定元素可以通过索引访问

3、所有的数组都是由连续的内存位置组成

4、最低的地址对应第一个元素,最高的地址对应最后一个元素

5、虽然分配了空间,但是没有存储数据的地址强行取值会发生数组越界

# 声明数组

声明一个类型为 int 的最多包含 10 个元素的数组 tags,声明语句如下:

int tags[10];

# 初始化数组

逐个初始化数组,大括号 { } 列举:

int tags[3] = {5, 6, 8}; // 最多3个

不限制元素的个数:

int tags[] = {5, 6, 8, 2, 4}; 

修改数组中某个元素值:

tags[2] = 50;

# 访问数组元素

通过数组名称加索引进行访问:

int tag = tags[2];

# 多维数组

声明创建了一个二维 整型数组:

int coords[3][4];

声明创建了一个三维 整型数组:

int cube[3][4][5];

# 初始化多维数组

初始化二维数组

下面是一个带有 3 行 4 列的数组:

int coords[3][4] = {  
 {0, 1, 2, 3} ,   /*  初始化索引号为 0 的行 */
 {4, 5, 6, 7} ,   /*  初始化索引号为 1 的行 */
 {8, 9, 10, 11}   /*  初始化索引号为 2 的行 */
};

与上面是等同的:

int coords[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};

# 指向数组的指针

int tags[3] = {5, 6, 8}; 

// 1、tags 是指向首地址的,指向 &tags[0] 的指针
int sec = *(tags + 1); // 通过指针和下标取值

int *p;
p = tags; // 指针新名称

int one = *p;
int sec = *(p+1);
int th = *(p+2);

# 传递数组给函数

// 形式参数是一个指针:
void func_1(int *arr)
{
}

// 形式参数是一个已定义大小的数组:
void func_2(int arr[3])
{
}

// 形式参数是一个未定义大小的数组
void func_3(int arr[])
{
}

# 函数返回数组

1、函数不能之间返回数组对象,可以返回数组指针

2、如果返回的是局部变量数组(默认分配在栈空间)指针,那么调用时这个对象已经释放了,这是不对的

3、可以返回堆内存的数组指针(需要手动new 和 delete)

4、可以直接返回全局变量指针,或者静态对象指针等等

示例:

#include <iostream>
using namespace std;
 
int * func_re()
{
  // int tags[3] = {5, 6, 8}; 这个不行,返回时对象将被系统释放了
  
  int *tags = new int[2]; // 通过new 分配堆内存对象
  tags[0] = 5; 
  tags[1] = 8; 
  return tags;
}

int main()
{
    int *tags = func_re(); 
    cout << tags[0] << "," << tags[1] << endl;
    
    delete[] tags; // 通过delete 释放开辟的空间
}

# 字符串

# C 字符串

#include <iostream>
#include <cstring>

using namespace std;

int main ()
{
    char hellos[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
    char str1[11] = "Hello";
    char str2[11] = "World";
    char str3[11];
    int  len ;

    strcpy(str3, str1);
    cout << "复制 str1 到 str3: " << str3 << endl;

	  char *str4;
    str4 = strcat(str1, str2);
    cout << "连接 str1 和 str2: " << str4 << endl;

    len = strlen(str4);
    cout << "连接后,str4 的总长度: " << len << endl;
    return 0;
}

# C++ 字符串

C++ 标准库对这些运行增加了运算符的支持,使得操作简单化:

#include <iostream>
#include <string>

using namespace std;

int main ()
{
    string str1 = "Hello";
    string str2 = "World";
    string str3;
    int  len ;

    str3 = str1;
    cout << "复制 str1 到 str3 : " << str3 << endl; 

    str3 = str1 + str2;
    cout << "连接 str1 和 str2: " << str3 << endl;

    len = str3.size();
    cout << "连接后,str3 的总长度 :  " << len << endl;
    return 0;
} 

# 指针

# 访问内存地址

可使用连字号(&)运算符访问的地址:

#include <iostream>

using namespace std;

int main (){
    int  a = 2;
    cout << "a 变量的地址:" << &a << endl;
    return 0;
}

结果:

a 变量的地址:0x7ffe0112efec

# 指针?

指针是一个变量,存储内存位置的直接地址,声明时加上*号:

#include <iostream>

using namespace std;

int main (){
    int a = 2;
    cout << "a 变量的值:" << a << endl;
    cout << "a 变量的地址:" << &a << endl;

    int *p; // 指针变量的声明
    p = &a; // 指针变量存储对象地址

    cout << "指针变量p变量的地址:"<< p << endl;
    cout << "指针变量p变量的地址上的值:"<< *p << endl;
  
    return 0;
}

结果:

a 变量的值:2
a 变量的地址:0x7ffc6eeeeb04
指针变量p变量的地址:0x7ffc6eeeeb04
指针变量p变量的地址上的值:2

# 空指针

NULL 指针是一个定义在标准库中的值为零的常量。

#include <iostream>
using namespace std;

int main ()
{
   int  *p = NULL;

   cout << "p 的值是 " << ptr ;
 
   return 0;
}

结果:

p 的值是 0

# 指针移动

指针+1 表示当前对象内存地址偏移到下一个对象的内存地址上

指针-1 表示当前对象内存地址偏移到上一个对象的内存地址上

#include <iostream>
using namespace std;

class Person
{
   public:
      int borth_y;
      int lenght;
      int age;
};

int main( )
{
    Person person;
    person.borth_y = 2018;
    person.lenght = 100;
    person.age = 4;

    int *p = &person.lenght; // 每次移动4字节内存

    cout << "指针变量p变量的地址值:"<< *(p) << endl;
    cout << "指针变量p变量的下一个地址值:"<< *(p+1) << endl;
    cout << "指针变量p变量的上一个地址值:"<< *(p-1) << endl;

    return 0;
}

结果

指针变量p变量的地址值:100
指针变量p变量的下一个地址值:4
指针变量p变量的上一个地址值:2018

发现规律了吧

# 指针和数组

前面介绍了,一个对象三个成员之间可以通过指针移动来获取,并且取值结果通常是同类型的值

那么显然这很符合数组的规律,很好解释了数组的下标操作数据的原理:

#include <iostream>
using namespace std;


int main( )
{
   int ages[6] = {10, 13, 8, 4, 7, 3};
   cout << "ages[0] = "<< ages[0] << endl;
   cout << "ages[1] = "<< ages[1] << endl;
   cout << "ages[2] = "<< ages[2] << endl;
	
   int *p = ages;
	
   cout << "p = "<< *(p) << endl;
   cout << "p+1 = "<< *(p+1) << endl;
   cout << "p+2 = "<< *(p+2) << endl;

   return 0;
}

结果

ages[0] = 10
ages[1] = 13
ages[2] = 8
p = 10
p+1 = 13
p+2 = 8

结果和操作数组一样,其实本质是一样的。

# 指向指针的指针

指向指针的指针是一种多级间接寻址的形式,或者说是一个指针链:

1、变量 :存储 对应数据

2、p指针:存储 变量的地址

3、指针的指针:存储 p指针的地址

#include <iostream>
using namespace std;

int main( )
{
   int  age = 18; // 变量
   int  *p = &age; // p指针 存储 变量的地址
   int  **p_p = &p; // 指针的指针  存储 p指针的地址

   cout << "age = " << age << endl;
   cout << "*p = " << *p << endl;
   cout << "**p_p = " << **p_p << endl;

	cout << "age地址 = " << &age << endl;
   cout << "指针p值 = " << p << endl;
	cout << "指针p地址 = " << &p << endl;
   cout << "指针p_p值 = " << p_p << endl;
	
   return 0;
}

结果

age = 18
*p = 18
**p_p = 18

age地址 = 0x7ffc9463e594
指针p值 = 0x7ffc9463e594

指针p地址 = 0x7ffc9463e588
指针p_p值 = 0x7ffc9463e588

# 函数指针参数

#include <iostream>
using namespace std;

void fun1(int *p)
{
   cout << "*p = " << *p << endl;
}

int main( )
{
    int  age = 18;
    int  *p = &age; // 指向int的指针

    fun1(p);
    return 0;
}

结果

*p = 18

# 函数返回指针

#include <iostream>
using namespace std;

int * fun2(int *p)
{
    return p;
}

int main( )
{
    int  age = 18;
    int  *p = &age; // 指向int的指针

    int  *p2 = fun2(p);
    cout << "*p2 = " << *p2 << endl;
    return 0;
}

结果

*p2 = 18

# 引用(别名)

# 引用

引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字(引用不能指向null)

引用 和 指针:

1、引用必须指向合法的内存,指针不用

2、引用一个对象后不能被指向到另一个对象,指针可以

3、引用必须在创建时被初始化,指针可以在任何时间被初始化

示例:

引用通过 类型+& 声明

#include <iostream>
using namespace std;

int main( )
{
    int  age = 18;

    // 声明引用变量
    int& A = age;

    cout << "age = " << age << endl;
    cout << "A = " << A << endl;
    return 0;
}

结果:

age = 18
A = 18

A 是 age 的别名,使用相同

# 引用作为参数

#include <iostream>
using namespace std;

void fun1(int& a)
{
   cout << "A = " << a << endl;
}

int main( )
{
    int  age = 18;

    // 声明引用变量
    int& A = age;

    fun1(A);

    return 0;
}

# 函数中返回引用

#include <iostream>
using namespace std;

int& fun2(int& a)
{
  return a;
}

int main( )
{
    int  age = 18;

    // 声明引用变量
    int& A = age;

    int& A2 = fun2(A);
    cout << "A2 = " << A2 << endl;
    return 0;
}

# 流

# 标准输入输出流

iostream 输入/输出库

输入:cin

输出:cout

#include <iostream>
using namespace std;

int main(){
    char name[50];
    cout << "输入名称:" << endl;
    cin >> name;
    cout << "您好 " << name << endl;   
} 

结果:

输入名称:
您好 Dean

# 标准错误流(cerr)

cerr 是 ostream 类的一个实例。

cerr 将错误信息【立即】显示到显示屏

#include <iostream>
using namespace std;
 
int main(){
    char str[] = "open fail !";
    cerr << "Error : " << str << endl; 
} 

结果:

Error : open fail !

# 标准日志流(clog)

clog 是 ostream 类的一个实例。

clog 将日志信息显示到显示屏

但是 clog 对象是缓冲的,缓冲填满或者缓冲区刷新时才会输出。

#include <iostream>
using namespace std;

int main(){
    char str[] = "load success !";
    clog << "🍻 : " << str << endl;
} 

当上面的代码被编译和执行时,它会产生下列结果:

🍻 : load success !

# 数据结构struct

# 定义结构

struct Books{
    char title[50];
    char author[50];
    char subject[100];
    int price;
} book;  

# 结构的使用

#include <iostream>
#include <cstring>
 
using namespace std;
void printBook( struct Books book );
Books book(string t, int pri);

struct Books{
    string title;
    int price;
};
 
int main(){
    Books book1 = book("财经", 34);

    // 输出 book1 信息
    printBook( book1 );

    return 0;
}

// 创建并返回一个结构体
Books book(string t, int pri) {
	struct Books book; 
	book.title = t;
	book.price = pri;

	// Books *bp = &book;
	return book;
}

// 结果体作参数
void printBook( struct Books book ){
    cout << "Book title : " << book.title <<endl;
    cout << "Book price : " << book.price <<endl;
}

结果:

Book title : 财经
Book price : 34

# typedef (别名)

typedef 可以给结构体取别名(类雏形),不同于引用别名,引用只能是已赋值对象的别名。

例如:

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

typedef struct
{
   string title;
   int price;
}Books;

int main(){
	Books book; 
	book.title = "书名";
	book.price = 23;

	cout << "Book title : " << book.title <<endl;
    cout << "Book price : " << book.price <<endl;
	
    return 0;
}

结果:

Book title : 书名
Book price : 23

可以使用 typedef 关键字来定义非结构类型,如下所示:

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

int main(){
    // 给 “unsigned short int” 取别名 usint
    typedef unsigned short int usint;
    usint x = 2;
    cout << "x : " << x <<endl;

    return 0;
}

结果

x : 2
C++基础概念(上)
C++语法速查

← C++基础概念(上) C++语法速查→

Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式