• C++ 基础一


    准备工具Vscode或者Clion或者Dev C++或者Vs studio 和
    MSYS2 是C++跨平台的重要工具链.

    准备工作

    安装MSYS2

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    pacman -S mingw-w64-ucrt-x86_64-gcc 后Y

    最后用cmd gcc --version

    在这里插入图片描述
    环境变量添加进去:
    在这里插入图片描述

    软件

    CLion

    创建文件

    右击–New–C/C++ Source File
    在这里插入图片描述
    在这里插入图片描述

    或者导入vs2019的环境

    一、基本介绍

    1.1C++源文件

    该文件一般是以.cpp 或者 .cxx 后缀结尾的。

    #include
    using namespace std;
    // main有且仅有一个
    int main() {
    
    	cout << "Hello C++__world" << endl;
    	//system("pause");
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述
    main 函数只包含一行代码:这个单条语句是以 std 开头,然后以一个分号(;)作为结尾
    的。

    1.2 代码注释

    注释是一种编写代码时用来解释程序的作用和用途的特殊语句,编译器会自动检测并忽略,注释并不对程序功能产生任何影响。

    格式:
    (1)单行注释: // 后接对代码的描述
    放置在代码上方,或者代码语句结束的结尾较好。

    (2)多行注释:/*多行注释*/
    这个由于可能代码篇幅可能较长,所以推荐写在整体的上方。

    1.3变量与常量

    为了能准确的在某可执行数据操作的空间的提前预备,可以使用&运算符检索内存地址
    
    • 1

    在编程中,必须声明变量是因为这使得程序员能够给特定的值或数据类型赋予一个名称,从而在后续代码中更容易地访问和使用该值或数据类型。声明变量还使程序员能够指定该变量可以存储的数据类型,这有助于防止数据类型错误,并确保程序正确运行。

    1.3.1变量

    给一段指定的内存空间起名,方便操作这段内存
    
    • 1

    语法数据类型 变量名 = 初始值;

    注意:最好是在定义的时候,给变量赋初值。因为变量是在操作指定的内存空间,在定义变量的时候,会找某一空间,却不可保证改空间原先的值是没有的。

    #include
    using namespace std;
    
    int main() {
    	//最好是在定义的时候,给变量赋初值。
    	int a = 5;
    	//带有中文输出的内容,需要把编码格式改为GBK
    	cout << "a 的值= " << a << endl;
    	
    	system("pause");
    
    	return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    名称只能使用字母字符、数字和下划线:这是C++的基本字符集,名称不能包含空格、标点符号等其他字符。名称的第一个字符不能是数字:名称的第一个字符必须是字母或下划线。

    区分大写字符与小写字符:C++是区分大小写的编程语言,因此,变量myVariable和myvariable会被视为两个不同的变量。

    不能将 C++关键字用作名称:C++有一些保留的关键字,如int、if、for等,这些关键字不能被用作变量或函数的名称。

    以两个下划线或下划线和大写字母打头的名称被保留给实现使用:这种命名方式通常用于系统级函数或变量,开发者一般不应使用这种方式命名自己的变量或函数。

    以下划线开头的名称被保留给实现,用作全局标识符:这也是系统级函数或变量的命名方式。

    C++对于名称的长度没有限制:理论上,名称的长度只受到可用内存的限制。\

    然而,在实际开发中,过长的名称可能会降低代码的可读性。

    1.3.2 常量

    不随任何的行为而改变自身数据
    
    • 1

    语法
    (1)#define 宏定义 #define 常量名 常量值
    源文件的上方定义的

    (2)const 修饰的变量 const 数据类型 常量名 = 常量值
    被const修饰该变量为常量,不可修改

    1.3.3 二者的区别:

    虽两种方式都可以用来定义常量,但仍存在一些区别:

    1. #define 宏常量:

      • 使用预处理指令,简单替换,没有类型检查。
      • 不占用内存,直接替换为常量值(是简单的文本替换,它将符号替换成相应的文本; 即:#define 定义的常量没有分配存储空间,没有对应的地址)。
      • 可以定义函数、表达式等,不仅仅限于常数(define可以采用表达式作为名称)。
      • 宏不受作用域限制,全局可用。
    2. const修饰的变量:

      • 是真正的变量,具有数据类型,会占用内存。(因为const 定义的常量在内存中分配了存储空间,可以获取其地址
      • 提供类型安全,编译器会进行类型检查。
      • 有作用域限制,遵循普通变量的作用域规则。
      • 更推荐,因为具有类型信息,易于维护和调试。

    通常情况下,推荐使用 const 修饰的变量来定义常量,因为它更具类型安全性和可读性。

    1.3.4初始化(C/CPP有不同)

    (1)变量的
    // 方式一:C语言的
      int x=123;
    // 方式二:CPP中特有的
      int a(23434);
      cout << a;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    (1)以数组定义的形式定义数据
    int main()
    {
      int x = {10};
      int y{123};
    
      if (typeid(x) == typeid(int))
      {
        cout << "x的类型是:int" << endl;
      }
       if (typeid(y) == typeid(int))
      {
        cout << "y的类型是:int" << endl;
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    (2)若括号中无数据,则初始化为零的值

    在这里插入图片描述
    C++11引入了一种更统一、更直观的初始化方式,即使用大括号进行初始化。这种方式的优点是它适用于所有类型,包括基础类型和自定义类型。此外,它还可以直接在类定义中指定初始值,这使得代码更清晰、更易于理解。

    大括号初始化方式还可以直接在类定义中指定初始值。这种方式使得代码更加清晰、易于理解,特别是对于那些需要初始化的类成员变量。通过在类定义中使用大括号初始化,可以确保在对象创建时,成员变量能够被正确地初始化,从而避免了在构造函数中进行繁琐的初始化操作。

    class Person {  
    public:  
        std::string name;  
        int age;  
      
        Person(std::string n, int a) : name(n), age(a) {  
            // 构造函数中不需要进行任何初始化操作  
        }  
    };  
      
    int main() {  
        Person person("John Doe", 30); // 使用大括号初始化方式初始化成员变量  
        return 0;  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    1.4 关键字和标识符

    C++中的关键字是指具有特殊含义的保留单词,例如"int"和"if"

    在给变量或者常量起名称时候,不要用C++得关键字,否则会产生歧义。
    
    • 1

    在这里插入图片描述

    标识符是程序员定义的用于命名变量、函数等的名称。 给标识符命名时,争取做到见名知意的效果,方便自己和他人的阅读

    • 标识符不能是关键字
    • 标识符只能由字母、数字、下划线组成
    • 第一个字符必须为字母或下划线
    • 标识符中字母区分大小写

    1.5 名称空间

    C++中的命名空间(namespace)是一种用于组织代码的机制。它允许将相关的类、函数和变量放置在一个逻辑上的容器中,以避免命名冲突和提高代码的可读性。

    可以使用关键字namespace后跟命名空间的名称。

    namespace myNamespace {
        // 声明和定义类、函数、变量等
        class MyClass {
            // 类的成员声明和定义
        };
    
        void myFunction() {
            // 函数的定义
        }
    
        int myVariable = 10;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在使用命名空间中的元素时,可以通过使用命名空间的名称来限定它们。

    int main() {
        myNamespace::MyClass obj;
        myNamespace::myFunction();
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    这样做可以避免与其他命名空间或全局命名空间中的相同名称的元素发生冲突。

    1.6 Cpp语句

    "语句"是编程中的一个基本概念,它是构成程序的基本单元。在编程中,我们通过编写各种语句来实现程序的各种功能。

    1.6.1声明语句 (Declaration statement):

    在编程中,声明语句用于定义变量的名称和类型。例如,在C语言中,可以使用“int x;”来声明一个名为“x”的整数变量。

    1.6.2 赋值语句

    用于将一个值赋给一个变量。赋值语句通常由一个赋值操作符(例如“=”)和一个值组成,该值被赋给左边的变量。以分号为结尾

    赋值语句 (Assignment statement):赋值语句用于将一个值赋给一个变量。在大多数编程语言中,这通常通过使用赋值运算符(例如C语言中的“=”)来完成。例如,“x = 5;”将值5赋给变量x。

    1.6.3消息语句 (Message statement):

    消息语句通常用于面向对象编程(OOP)中。它涉及到向对象发送消息,以请求对象执行某个操作或方法。例如在C++中,你可以使用对象指针或对象引用来调用成员函数,从而实现类似于消息传递的效果。

    class MyClass {  
    public:  
        void myFunction() {  
            // Do something  
        }  
    };  
      
    int main() {  
        MyClass obj;  
        obj.myFunction(); // 使用对象调用成员函数  
      
        MyClass* ptr = &obj;  
        ptr->myFunction(); // 使用对象指针调用成员函数  
          
        return 0;  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    obj.myFunction()和ptr->myFunction()都可以用来调用myFunction()成员函数。在这种情况下,你可以将obj和ptr视为消息传递的接收者(即消息的接收对象)。

    1.6.4 函数调用 (Function call):

    函数调用是执行一个函数的过程。当你想使用一个函数的功能时,就需要调用它。函数调用通常包括函数名称以及传递给函数的参数。例如,在Python中,“result = my_function(arg1, arg2);”是一个函数调用的示例,其中“my_function”是函数名称,“arg1”和“arg2”是传递给该函数的参数。Java、Cpp也是一样的

    1.6.5函数原型 (Function prototype):

    函数原型是函数的声明,它描述了函数的返回类型、参数数量以及参数的类型。这通常出现在任何使用该函数的代码之前。例如,在C语言中,“int add(int a, int b);”是一个函数原型,其中“int”是返回类型,“add”是函数名称,“int a”和“int b”是参数列表。

    1.6.6返回语句 (Return statement):

    返回语句用于结束一个函数的执行,并将结果(如果需要)返回给调用该函数的代码。在C语言中,“return result;”是一个返回语句的示例,其中“result”是要返回的值。如果函数没有返回任何值,则可以使用“return;”来结束函数的执行。

    二、数据类型

    C++中的数据类型可以分为
    好的,我会继续介绍C++中常见的基本数据类型和用户定义数据类型。

    2.1 基本数据类型:

    检验类型大小 ` sizeof(数据类型、变量) `
    
    • 1

    C++是一种静态类型语言,这意味着在创建变量或常量时必须明确指定其数据类型。编译器需要在编译时确定每个变量的数据类型,以便正确分配内存并执行相应的操作。

    如果不指定数据类型,编译器将无法正确处理变量的内存分配和操作,因此必须明确定义数据类型。

    2.1.1整型:

    climits 是 C++ 标准库中的一个头文件,它定义了一些表示整数类型的极限的符号常量
    在这里插入图片描述

    用于表示整数类型的数据,可以是正数、负数或零。区别在于存储的空间大小不同 
    
    • 1

    short < int <= long <= long long

    short:2字节 -2^15 - 2 ^15 -1
    int :4字节 -2^31 - 2 ^31 -1
    long:在32位系统上通常4字节, 在64位系统上通常8字节, -2^31 - 2 ^31 -1
    long long :8字节 -2^15 - 2 ^63 -1

    2.1.2 浮点型 (实数):

    用于表示带有小数的数值,其中`float`表示单精度浮点数,而`double`表示双精度浮点数。
    
    • 1
    1. float:

      • float 是一种单精度浮点数数据类型,通常占用4字节(32位),可以存储大约7位有效数字。
      • 使用 f 后缀来明确指定一个浮点数为 float 类型,如 3.14f
    2. double:

      • double 是一种双精度浮点数数据类型,通常占用8字节(64位),可以存储大约15-16位有效数字。
    3. 科学计数法:

      • C++支持科学计数法来表示浮点数,使用形如 aeb 的表示法,其中 a 是系数,e 是底数为10的指数,b 是指数的符号。例如,3e2 表示 (3 *10^2),即300;0.03 可以写作 3e-2 表示 (3 *10^(-2))。

    示例:

    float pi = 3.14f; // 使用 f 后缀指定 float 类型
    double largeNumber = 1.234567890123456789; // 默认为 double 类型
    
    float a = 3e2; // 表示 300
    float b = 3e-2; // 表示 0.03
    
    • 1
    • 2
    • 3
    • 4
    • 5
    保留指定位数的小数
    使用iomanip库中的setprecision函数
    fixed和setprecision函数来设置输出的小数精度。fixed用于固定小数点的位置,setprecision用于设置小数的位数。
    
    • 1
    • 2
    #include 
    #include 
    using namespace std;
    
    int main() {
        double num = 3.1415926;
        int precision = 3; // 保留3位小数
    
        cout << fixed << setprecision(precision) << num << endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    字符串流(stringstream)
    
    • 1
    
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    
    int main() {
        double num = 3.1415926;
        int precision = 3; // 保留3位小数
    
        stringstream ss;
        ss << fixed << setprecision(precision) << num;
        string result = ss.str();
    
        cout << result << endl;
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    我们使用字符串流(stringstream)来将浮点数转换为字符串,并设置小数的位数。然后,我们可以将结果存储在一个字符串变量中,以便后续使用。

    进制
    #include   
      
    int main() {  
        int num = 42;  
        std::cout << "Decimal: " << num << std::endl;  
        std::cout << "Hexadecimal: " << std::hex << num << std::endl;  
        std::cout << "Octal: " << std::oct << num << std::endl;  
        return 0;  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    在这里插入图片描述

    2.1.3 字符型 (char 1个字节):

    作用: 用于表示单个字符,以ASCII编码1为基础。可以当做比short更小的整型

    语法: char ch = 'a';

    注意
    ( 1 )用单引号括起字符,示例:char myChar = 'A';
    ( 2 )单引号内只能包含一个字符,不能是字符串,示例:char myChar = 'AB'; 是不允许的,应该是 char myChar = 'A';
    ( 3 )字符型变量(char)在C和C++中通常占用1个字节(8位),无论是用于存储字符本身还是对应的ASCII码。

    2.1.3.(1)转义字符

    用于表示一些不能显示出来的ASCII字符

    转义字符是在字符前面加上反斜杠(\)来表示一些特殊字符或操作,通常用于在字符串或字符常量中插入不易直接输入的字符。

    常用的转义字符有: \n \\ \t

    当我们使用字符类型(char)作为数值类型时

    有符号的 char(signed char)和无符号的 char(unsigned char)之间的差异是非常重要的。通常情况下,unsigned char 的取值范围为 0 到 255,而 signed char 的取值范围则为 -128 到 127。因此,如果我们尝试在一个 char 变量中存储一个大于 127 或小于 -128 的数值,可能会导致溢出或数据不准确的问题。相比之下,使用 unsigned char 可以确保我们能够存储更大范围的值,而不会遇到溢出问题。

    2.1.4 布尔型 (bool):

    布尔类型(bool)是一种用于表示真(true)或假(false)的数据类型,在C++中占用1个字节大小。它是用来做逻辑判断的基本类型。

    bool flag = true;
    	cout << flag << endl; // 1
    
    	flag = false;
    	cout << flag << endl; // 0
    
    	cout << "size of bool = " << sizeof(bool) << endl; //1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2. 2 用户定义数据类型(后续):

    • 结构体 (struct): 允许创建包含多个不同数据类型的组合体,可以通过结构体定义多个变量来描述一个实体的属性。
    • 类 (class): 允许创建具有成员变量和成员函数的自定义数据类型,实现了面向对象编程的概念,包括封装、继承和多态。
    • 枚举类型 (enum): 允许创建一个包含一组命名常量的新数据类型。
    • 共用体 (union):共用体允许在同一内存位置存储不同的数据类型。这意味着共用体的成员共享内存,修改一个成员会影响到其他成员。
    • typedef 定义的类型:typedef 是用来为现有类型定义新的名称,提高代码的可读性和可维护性。

    2.3 字符串型

    在C++中,字符串类型可以属于两种类型:普通类型和用户定义类型,具体取决于使用的字符串表示方式。

    1. 普通类型(延续C语言风格):

      • 在C++中,可以使用字符数组(char array)或指向字符的指针来表示字符串。这种方式属于普通类型,没有特定的用户定义类型,它们是C和C++的基本字符串表示方式。
      char str1[] = "Hello, world!";  // 字符数组表示字符串
      char* str2 = "Hello, world!";    // 字针表示字符串
      
      • 1
      • 2
    2. 用户定义类型:

      • 另一方面,C++也提供了标准库中的 std::string 类,这是一个用户定义的字符串类型。std::string 是一个类,提供了丰富的字符串操作功能和方便的字符串管理。
      #include 
      
      std::string str = "Hello, world!";  // 使用 std::string 类型
      
      • 1
      • 2
      • 3

    std::string 是C++标准库中的一部分,它提供了很多方便的字符串处理方法,例如字符串拼接、查找、替换等操作,使得字符串处理更方便和高效。

    因此,字符串可以是普通类型(字符数组或指针)或用户定义类型(std::string),具体取决于你选择的字符串表示方式。如果需要更多信息或有其他问题,请随时提出。

    2.4 键入键出

    C++为处理输入和输出提供了两个预定义的对象(cin和cout),它们是istream和ostream类的实例。这两个类定义在iostream文件中。为ostream类定义的插入运算符(<<):导致数据插入到输出流中。可能:为istream类定义的提取运算符(>>):能够从输入流中提取信息。cin和cout都是智能对象,可以自动根据程序上下文将信息从一种形式转换为另一种形式。

    2.4.1 数据键入

    作用:用于从键盘获取数据

    关键字: cin

    语法: cin >> 变量

    cin通常与运算符>>一起使用,用于将输入的数据存储到指定的变量中。这样可以方便地从用户那里接收输入,并在程序中进行处理

    int x = 0;
    	cout << "请输入整型变量x的值:" << endl;
    	cin >> x;
    	cout << x << endl;
    
    • 1
    • 2
    • 3
    • 4

    ‘>>’是提取运算符,用于从输入流中提取数据。具体来说,它用于从输入流(如cin)中读取数据并将其赋值给右侧的操作数。例如,cin >> x;将从标准输入读取一个值并将其存储在变量x中。

    2.4.2 使用cout输出

    <<是插入运算符,用于将右侧的内容发送到左侧的对象。
    减少使用printf的复杂性,%s、%d造成的复杂度
    cout是C++中的输出流对象,其使用更加简单、直观。cout可以自动识别数据类型,并直接输出,无需使用格式化指令。此外,cout还具有可扩展性,可以通过重载<<运算符来输出新的数据类型。这使得cout更加灵活,能够适应更多的应用场景。

    换行

    (1)控制符endl:
    在C++中,你可以使用std::cout来打印字符串。如果你想在两个字符串之间添加空格,你可以简单地将空格包含在字符串中。、

    (2)换行符‘\n’

    区别:

    两者的区别在于,使用endl可以确保在程序继续之前刷新输出(立即显示在屏幕上),而使用\n则无法提供这样的保证。

    在C++中,为了提高I/O效率,通常会使用缓冲区。也就是说,当我们进行输出操作时,实际上并不会立即把数据写入到文件或屏幕上,而是先写入到缓冲区中,当缓冲区满了或者遇到某些特定的操作(比如endl)时,才会把缓冲区的内容写入到真正的目标位置。

    `
    因此,当我们使用endl时,实际上是在告诉C++的I/O系统:“请立即把所有缓冲区的内容都写入到文件或屏幕上,并刷新缓冲区。”这就是为什么说使用endl可以确保在程序继续执行之前,任何之前的输出都已经完全显示出来。

    2.4.3设置输出的宽度和精度

    在C++中,可以使用iomanip库中的setw和setprecision函数来设置输出的宽度和精度。

    #include   
    #include   
      
    using namespace std;  
      
    int main() {  
        double pi = 3.14159265358979323846;  
        cout << setw(10) << setprecision(3) << pi << endl;  
        return 0;  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    setw函数设置的宽度是指整个输出宽度,包括小数点、符号等。因此,如果需要输出指定位数的小数,需要使用setprecision函数来设置精度。

    三、运算符

    在这里插入图片描述
    注意(1) 两个小数不可做取模运算,结果看左边

    	int a3 = 10;
    	int b3 = 0;
    	//报错,除数不可以为0
    	//cout << a3 / b3 << endl; 
     
      // 两个小数不可做取模运算,结果看左边
      //  除数不为0
      cout << -10 % 3 << endl; //-1
      cout << 10 % 3 << endl;  // 1
    
    //两个小数可以相除
    	double d1 = 0.5;
    	double d2 = 0.25;
    	cout << d1 / d2 << endl;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    (2)赋值是‘=’ 等于是‘==’

    算术运算符
    在这里插入图片描述
    赋值运算符
    在这里插入图片描述
    比较运算符
    在这里插入图片描述

    逻辑运算符
    在这里插入图片描述

    3.1 运算符重载

    在C++中,<<运算符有两种主要的用法:

    作为左移运算符:这通常用于处理位操作和位移。例如,1 << 2会得到4(在二进制中,左移2位等于乘以2的2次方)。
    作为插入运算符:这是在C++中用于向输出流(如cout)插入数据。例如,cout << “Hello, world!”;会打印出"Hello, world!"。
    这两种用法在C++中都是合法的,编译器会根据上下文来确定使用哪种含义。这就是所谓的运算符重载:同一个运算符可以有多种不同的含义,具体取决于其上下文。

    然而,你不能重载<<运算符以改变其基本的左移或插入行为。你可以重载它,但你只能定义新的行为,不能改变已有的行为。例如,你不能定义cout << my_object;去做除了插入以外的其他事情。


    1. ASCII(American Standard Code for Information Interchange)编码将每个字符映射到一个唯一的整数。例如,字母 ‘a’ 对应的ASCII码是97。因此,当你在C或C++中创建一个字符型变量时,实际上是将该字符对应的ASCII码存储在内存中。 ↩︎

  • 相关阅读:
    【CGRect Objective-C语言】
    充分利用自动化测试的 10 个最佳实践
    Linux网络配置管理和设置
    Appium 移动端自动化测试,触摸(TouchAction) 与多点触控(MultiAction)
    vue项目中 jsconfig.json是什么
    BP神经网络的梯度公式推导(三层结构)
    Java 多线程:锁
    LAMMPS模拟:液滴润湿表面的铺展长度统计及Matlab平均计算
    依赖下载失败时,可以考虑一下这个方法
    Transformer模型:Encoder的self-attention mask实现
  • 原文地址:https://blog.csdn.net/m0_74154295/article/details/133436910