C++ 学习(基础语法篇)

2023-05-16

一、基础语法

1.1 C++ 简介

  • C++ 是一种静态类型的、编译式的、通用的、大小写敏感的、不规则的编程语言,支持过程化编程、面向对象编程和泛型编程。
  • C++ 是 C 的一个超集,事实上,任何合法的 C 程序都是合法的 C++ 程序。
  • 使用静态类型的编程语言是在编译时执行类型检查,而不是在运行时执行类型检查。

面向对象程序设计

  • 完全支持面向对象的程序设计,包括面向对象开发的四大特性:封装、抽象、继承、多态。

标准库

  1. 核心语言,提供了所有构件块,包括变量、数据类型和常量,等等。
  2. C++ 标准库,提供了大量的函数,用于操作文件、字符串等。
  3. 标准模板库(STL),提供了大量的方法,用于操作数据结构等。

ANSI 标准

  • 所有的C++编译器制造商均支持ANSI 标准,能够保证其便携性(代码在Mac、UNIX、Windows、Alpha 计算机上都能通过编译)。

1.2 C++ 环境设置

文本编辑器

编译器

  • 写在源文件中的源代码是人类可读的源。它需要"编译",转为机器语言,这样 CPU 可以按给定指令执行程序。
  • 大多数的 C++ 编译器并不在乎源文件的扩展名,但是如果您未指定扩展名,则默认使用 .cpp。
  • 常用的免费可用的编译器是 GNU 的 C/C++ 编译器

1.3 C++ 基本语法

C++ 程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互。

  • 对象 - 对象具有状态和行为,对象是类的实例。
  • - 类可以定义为描述对象行为/状态的 模板/蓝图。
  • 方法 - 从基本上说,一个方法表示一种行为。一个类可以包含多个方法。可以在方法中写入逻辑、操作数据以及执行所有的动作。
  • 即时变量 - 每个对象都有其独特的即时变量。对象的状态是由这些即时变量的值创建的。

C++ 程序结构

  • Eg:输出“Hello World”
  #include <iostream>
  using namespace std;
  
  // main() 是程序开始执行的地方
  int main()
  {
     cout << "Hello World"; // 输出 Hello World
     return 0;
  }
  • using namespace std; 告诉编译器使用 std 命名空间。

编译&执行 C++ 程序

  • 上述代码保存为“hello.cpp”,打开所在路径,输出“Hello World”
$ g++ hello.cpp
$ ./a.out

C++ 中的分号 & 语句块

  • 在 C++ 中,分号是语句结束符。也就是说,每个语句必须以分号结束。它表明一个逻辑实体的结束。
  • 语句块是一组使用大括号括起来的按逻辑连接的语句。

1.4 C++ 注释

  • /*开始*/结束(多行)
  • // 单行

1.5 C++ 数据类型

基本内置类型

类型关键字
布尔型bool
字符型char
整型int
浮点型float
双浮点型double
无类型void
宽字符型wchar_t

typedef 声明

  • 可以使用 typedef 为一个已有的类型取一个新的名字。typedef type newname;

枚举类型

  • 枚举类型(enumeration)是C++中的一种派生数据类型,它是由用户定义的若干枚举常量的集合。如果一个变量只有几种可能的值,可以定义为枚举(enumeration)类型。
  • 关键字 enum
enum 枚举名{ 
     标识符[=整型常数], 
     标识符[=整型常数], 
... 
    标识符[=整型常数]
} 枚举变量;
  • 如果枚举没有初始化, 即省掉"=整型常数"时, 则从第一个标识符开始。例如,下面的代码定义了一个颜色枚举,变量 c 的类型为 color。最后,c 被赋值为 “blue”。
enum color { red, green, blue } c;
c = blue;
  • 默认情况下,第一个名称的值为 0,第二个名称的值为 1,第三个名称的值为 2,以此类推。但是,您也可以给名称赋予一个特殊的值,只需要添加一个初始值即可。例如,在下面的枚举中,green 的值为 5。blue 的值为 6,因为默认情况下,每个名称都会比它前面一个名称大 1,但 red 的值依然为 0。
enum color { red, green=5, blue };

1.6 C++ 变量类型

  • 大写字母和小写字母是不同的,因为 C++ 是大小写敏感的。

C++ 中的变量声明

  • 使用extern声明变量,使用多个文件且只在其中一个文件中定义变量。
  • 变量可以声明多次,但只能定义一次。
  • extern作用:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。此外extern也可用来进行链接指定。
  • 在文件t2.cpp中有代码:
int x = 10;

在文件t1.cpp中有代码:

#include <iostream>
using namespace std;

extern int x;
int main() {
    cout << x;

    return 0;
}

输出:10
extern表示声明一个变量,声明使得这个名字为程序所指,而定义创建了和这个名字相关联的实体。
如:

int x = 10;

则是定义一个变量。
声明和定义分开,这样的意义就是可以在一个文件中使用另一个文件的变量,如上面的t1.cpp使用t2.cpp的变量。

C++ 中的左值(Lvalues)和右值(Rvalues)

  • 左值(lvalue):指向内存位置的表达式被称为左值(lvalue)表达式。左值可以出现在赋值号的左边或右边。
  • 右值(rvalue):术语右值(rvalue)指的是存储在内存中某些地址的数值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不能出现在赋值号的左边。
  • 变量是左值,数值型的数字是右值(Eg:10)

1.7 C++ 变量作用域

  • 作用域是程序的一个区域,一般来说有三个地方可以定义变量:
    • 在函数或一个代码块内部声明的变量,称为局部变量。
    • 在函数参数的定义中声明的变量,称为形式参数。
    • 在所有函数外部声明的变量,称为全局变量。
  • 在程序中,局部变量和全局变量的名称可以相同,但是在函数内,局部变量的值会覆盖全局变量的值。
  • 初始化局部变量和全局变量
    • 当局部变量被定义时,系统不会对其初始化,必须自行对其初始化。定义全局变量时,系统会自动初始化为下列值:
      |数据类型| 初始化默认值|
      |-----|-----|
      |int| 0|
      |char| ‘\0’|
      |float |0|
      |double |0|
      |pointer |NULL|

1.8 C++ 常量

  • 常量是固定值,在程序执行期间不会改变。这些固定的值,又叫做字面量。
  • 常量可以是任何的基本数据类型,可分为整型数字、浮点数字、字符、字符串和布尔值。
  • 常量就像是常规的变量,只不过常量的值在定义后不能进行修改。
  • 整数常量:
    • 可以带一个后缀,后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long)

定义常量

  1. 使用 #define 预处理器。
#define identifier value
// eg:
#define LENGTH 10  
  1. 使用 const 关键字。
const type variable = value;
// eg:
const int  LENGTH = 10;
  1. 二者区别:
    用const的优点:会进行类型安全检查。而define没有安全检查,且可能会产生意料不到的错误。

1.9 C++ 修饰符类型

  • C++ 允许在 char、int 和 double 数据类型前放置修饰符。
  • 数据类型修饰符:signed、unsigned、long、short
  • 修饰符 signed、unsigned、long 和 short 可应用于整型,signed 和 unsigned 可应用于字符型,long 可应用于双精度型。
  • 修饰符 signed 和 unsigned 也可以作为 long 或 short 修饰符的前缀。例如:unsigned long int。

类型限定符

限定符含义
constconst 类型的对象在程序执行期间不能被修改改变。
volatile修饰符 volatile 告诉编译器不需要优化volatile声明的变量,让程序可以直接从内存中读取变量。对于一般的变量编译器会对变量进行优化,将内存中的变量值放在寄存器中以加快读写效率。
restrict由 restrict 修饰的指针是唯一一种访问它所指向的对象的方式。只有 C99 增加了新的类型限定符 restrict。
  • volatile作用:
    volatile关键字是防止在共享的空间发生读取的错误。只保证其可见性,不保证原子性;使用volatile指每次从内存中读取数据,而不是从编译器优化后的缓存中读取数据,简单来讲就是防止编译器优化。

1.10 C++ 存储类

  • 存储类定义 C++ 程序中变量/函数的范围(可见性)和生命周期。这些说明符放置在它们所修饰的类型之前。
    • auto
    • register
    • static
    • extern
    • mutable
    • thread_local (C++11)
    • 从 C++ 11 开始,auto 关键字不再是 C++ 存储类说明符,且 register 关键字被弃用。

auto

  • 自 C++ 11 以来,auto 关键字用于两种情况:声明变量时根据初始化表达式自动推断该变量的类型、声明函数时函数返回值的占位符。

register

  • register 存储类用于定义存储在寄存器中而不是 RAM 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(通常是一个词),且不能对它应用一元的 ‘&’ 运算符(因为它没有内存位置)
  • Eg:register int miles;
  • 寄存器只用于需要快速访问的变量,比如计数器。还应注意的是,定义 ‘register’ 并不意味着变量将被存储在寄存器中,它意味着变量可能存储在寄存器中,这取决于硬件和实现的限制。

static

  • static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,使用 static 修饰局部变量可以在函数调用之间保持局部变量的值。(局部静态变量不销毁)
  • static 修饰符也可以应用于全局变量。当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内。
#include <iostream>

// 函数声明 
void func(void);

static int count = 10; /* 全局变量 */

int main()
{
    while(count--)
    {
       func();
    }
    return 0;
}
// 函数定义
void func( void )
{
    static int i = 5; // 局部静态变量
    i++;
    std::cout << "变量 i 为 " << i ;
    std::cout << " , 变量 count 为 " << count << std::endl;
}

结果:

变量 i 为 6 , 变量 count 为 9
变量 i 为 7 , 变量 count 为 8
变量 i 为 8 , 变量 count 为 7
变量 i 为 9 , 变量 count 为 6
变量 i 为 10 , 变量 count 为 5
变量 i 为 11 , 变量 count 为 4
变量 i 为 12 , 变量 count 为 3
变量 i 为 13 , 变量 count 为 2
变量 i 为 14 , 变量 count 为 1
变量 i 为 15 , 变量 count 为 0

extern

  • extern 存储类用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。
  • extern 是用来在另一个文件中声明一个全局变量或函数,通常用于当有两个或多个文件共享相同的全局变量或函数。

mutable

  • 允许对象的成员替代常量。也就是说,mutable 成员可以通过 const 成员函数修改。

thread_local

  • 使用 thread_local 说明符声明的变量仅可在它在其上创建的线程上访问。 变量在创建线程时创建,并在销毁线程时销毁。 每个线程都有其自己的变量副本。
  • 可以将 thread_local 仅应用于数据声明和定义,thread_local 不能用于函数声明或定义。
thread_local int x;  // 命名空间下的全局变量
class X
{
    static thread_local std::string s; // 类的static成员变量
};
static thread_local std::string X::s;  // X::s 是需要定义的

void foo()
{
    thread_local std::vector<int> v;  // 本地变量
}
  • thread_local变量是C++ 11新引入的一种存储类型。它会影响变量的存储周期(Storage duration),C++中有4种存储周期

    1. automatic
    2. static
    3. dynamic
    4. thread
  • 有且只有thread_local关键字修饰的变量具有线程周期(thread duration),这些变量(或者说对象)在线程开始的时候被生成(allocated),在线程结束的时候被销毁(deallocated)。并且每 一个线程都拥有一个独立的变量实例(Each thread has its own instance of the object)。

  • thread_local可以和staticextern关键字联合使用,这将影响变量的链接属性(to adjust linkage)。

  • 适用范围:

    1. 命名空间下的全局变量
    2. 类的static成员变量
    3. 本地变量
  • 既然每个线程都拥有一份独立的thread_local变量,那么就有2个问题需要考虑:

    1. 各线程的thread_local变量是如何初始化的?
    • 每个线程都会进行一次单独初始化
    1. 各线程的thread_local变量在初始化之后拥有怎样的生命周期,特别是被声明为thread_local的本地变量(local variables)?
    • 声明为thread_local的本地变量在线程中是持续存在的,不同于普通临时变量的生命周期,它具有static变量一样的初始化特征和生命周期

1.11 C++ 运算符

  • 运算符是一种告诉编译器执行特定的数学或逻辑操作的符号
    • 算术运算符
    • 关系运算符
    • 逻辑运算符
    • 位运算符
    • 赋值运算符
    • 杂项运算符

算数运算符

+-*/%++

关系运算符

==!=><>=<=

逻辑运算符

&&||!=

位运算符

&|^
异或

赋值运算符

运算符描述实例
=简单的赋值运算符,把右边操作数的值赋给左边操作数C = A + B 将把 A + B 的值赋给 C
+=加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数C += A 相当于 C = C + A
-=减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数C -= A 相当于 C = C - A
*=乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数C *= A 相当于 C = C * A
/=除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数C /= A 相当于 C = C / A
%=求模且赋值运算符,求两个操作数的模赋值给左边操作数C %= A 相当于 C = C % A
<<=左移且赋值运算符C <<= 2 等同于 C = C << 2
>>=右移且赋值运算符C >>= 2 等同于 C = C >> 2
&=按位与且赋值运算符C &= 2 等同于 C = C & 2
^=按位异或且赋值运算符C ^= 2 等同于 C = C ^ 2
|=按位或且赋值运算符C

杂项运算符

运算符描述
sizeofsizeof 运算符返回变量的大小。例如,sizeof(a) 将返回 4,其中 a 是整数。
Condition ? X : Y条件运算符。如果 Condition 为真 ? 则值为 X : 否则值为 Y。
,逗号运算符会顺序执行一系列运算。整个逗号表达式的值是以逗号分隔的列表中的最后一个表达式的值。
.(点)和 ->(箭头)成员运算符用于引用类、结构和共用体的成员。
Cast强制转换运算符把一种数据类型转换为另一种数据类型。例如,int(2.2000) 将返回 2。
&指针运算符 & 返回变量的地址。例如 &a; 将给出变量的实际地址。
*指针运算符 * 指向一个变量。例如,*var; 将指向变量 var。

运算符优先级

  • 由高到低
类别运算符结合性
后缀() [] -> . ++ - -从左到右
一元+ - ! ~ ++ - - (type)* & sizeof从右到左
乘除* / %从左到右
加减+ -从左到右
移位<< >>从左到右
关系< <= > >=从左到右
相等== !=从左到右
位与 AND&从左到右
位异或 XOR^从左到右
位或 OR|从左到右
逻辑与 AND&&从左到右
逻辑或 OR||从左到右
条件?:从右到左
赋值= += -= *= /= %=>>= <<= &= ^= |=从右到左
逗号,从左到右
  • sizeof不是函数,而是运算符,如在malloc中常传入sizeof的运算结果,他是在运行之前就已经计算好了传入malloc函数中的

1.12 C++ 循环

循环类型

循环类型描述
while 循环当给定条件为真时,重复语句或语句组。它会在执行循环主体之前测试条件。
for 循环多次执行一个语句序列,简化管理循环变量的代码。
do…while 循环除了它是在循环主体结尾测试条件外,其他与 while 语句类似。
嵌套循环您可以在 while、for 或 do…while 循环内使用一个或多个循环。

循环控制语句

breakcontinuegoto
跳出(包括loop、switch)跳单次不建议使用

1.13 C++ 判断

嵌套语句

语句描述
if 语句一个 if 语句 由一个布尔表达式后跟一个或多个语句组成。
if…else 语句一个 if 语句 后可跟一个可选的 else 语句,else 语句在布尔表达式为假时执行。
嵌套 if 语句您可以在一个 if 或 else if 语句内使用另一个 if 或 else if 语句。
switch 语句一个 switch 语句允许测试一个变量等于多个值时的情况。
嵌套 switch 语句您可以在一个 switch 语句内使用另一个 switch 语句;switch case中最后用default表示余下所有情况
  • switch中括号里面的结果必须是数值型的,单个的char也相当于数值,要是整个字符串(字符数组或者string),铁定用不成。
  • 如果需要在switch-case里面定义局部变量,case的语句需要加大括号。

? : 运算符

A ? B : c;

A真则B,A假为C。

1.14 C++函数

  • 在函数声明中,参数的名称并不重要,只有参数的类型是必需的,因此第二条也是有效的声明:

    int max(int num1, int num2);
    
    int max(int, int);
    
  • 在一个源文件中定义函数且在另一个文件中调用函数时,函数声明是必需的。应该在调用函数的文件顶部声明函数。

  • 函数参数:

    • 函数使用参数,必须声明接受参数值的变量。这些变量称为函数的形式参数

    • 形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁

    • 当调用函数时,有三种向函数传递参数的方式:

      调用类型描述
      传值调用默认方法,该方法把参数的实际值复制给函数的形式参数。在这种情况下,修改函数内的形式参数对实际参数没有影响。
      指针调用该方法把参数的地址复制给形式参数。在函数内,该地址用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数
      引用调用该方法把参数的引用复制给形式参数。在函数内,该引用用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数
  • 参数默认值

    • 在函数定义中使用赋值运算符来为参数赋默认值。
    • 调用函数时,如果未传递参数的值,则会使用默认值,如果指定了值,则会忽略默认值,使用传递的值。
  • Lambda 函数与表达式

    • C++11 提供了对匿名函数的支持,称为 Lambda 函数(也叫 Lambda 表达式)。

    • Lambda 表达式把函数看作对象。Lambda 表达式可以像对象一样使用,比如可以将它们赋给变量和作为参数传递,还可以像函数一样对其求值。

    • 形式:

      [capture](parameters)->return-type{body}
      # eg:
      [](int x, int y){ return x < y ; }
      
      # 无返回值:
      [capture](parameters){body}
      # eg:
      []{ ++global_x; } 
      
      # 返回值类型可以明确指定:
      [](int x, int y) -> int { int z = x + y; return z + x; }
      
    • 在Lambda表达式内可以访问 当前作用域 的变量,这是Lambda表达式的闭包(Closure)行为。 与JavaScript闭包不同,C++变量传递有传值和传引用的区别。可以通过前面的[]来指定:

      []      // 沒有定义任何变量。使用未定义变量会引发错误。
      [x, &y] // x以传值方式传入(默认),y以引用方式传入。
      [&]     // 任何被使用到的外部变量都隐式地以引用方式加以引用。
      [=]     // 任何被使用到的外部变量都隐式地以传值方式加以引用。
      [&, x]  // x显式地以传值方式加以引用。其余变量以引用方式加以引用。
      [=, &z] // z显式地以引用方式加以引用。其余变量以传值方式加以引用。
      
    • 对于[=]或[&]的形式,lambda 表达式可以直接使用 this 指针。但是,对于[]的形式,如果要使用 this 指针,必须显式传入:

      [this]() { this->someFunc(); }();
      
  • 指针和引用的区别?

    • 指针是*,通过它能找到以它为地址的内存单元。
    • 引用是&,就是某个变量的别名,对引用操作与对变量直接操作完全一样。
    • 区别:
      1. 引用必须要初始化。
      2. 指针是个实体,而引用是别名。
      3. 引用只能在定义时被初始化一次,之后不可变,指针可以改变所指的对象。
      4. 可以有const指针,没有const引用。
      5. 指针自加,是指向下一次地址,而引用自加:是本身值的增加。
      6. 引用只能被初始化一次,不能再换成别的名字了。
  • 指针调用与引用调用的区别在于:

    • 指针变量存储的是一个指针,也就是一个存储地址,当使用指针作为形参的时候,可以改变指针的指向,访问该地址的数据时需要加上符号 * ;
    • 而引用调用他是直接将一个地址传递到函数内,相当于在该函数内给变量起了一个别名,不可改变指向,但可以改变该地址内所存储的值;

1.15 C++ 数字

  • int rand(void) 与 void srand(unsigned int seed)
    • 头文件:#include<stdlib.h>
    • 用户未设定随机数种子时,系统默认的随机数种子为1。rand()产生的是伪随机数字,每次执行时是相同的;若要不同,用函数srand()初始化它。
    • rand()和srand()要一起使用,其中srand()用来初始化随机数种子,rand()用来产生随机数。
    • 参数seed必须是个整数,通常可以利用time(0)的返回值或NULL来当做seed。如果每次seed都设相同值,rand()所产生的随机数值每次就会一样。(失去随机性)
    • 可以把 seed 设为 time(0) 保证随机性。
    • 要产生 0–n 内的随机数:rand() % n;a–b 内的随机数 a + rand() % (b - a + 1);左闭右开

1.16 C++ 数组

  • 存储一个固定大小相同类型元素的顺序集合

  • 所有的数组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素

声明数组

  • arraySize 必须是一个大于零的整数常量,type 可以是任意有效的 C++ 数据类型

    type arrayName [ arraySize ];
    

初始化数组

  • 如果不指定数组大小,则为初始化时元素的个数。

    double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
    
    double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
    

多维数组

  • type name[size1][size2]...[sizeN];

  • eg:初始化二维数组

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

指向数组的指针

  • 数组名是一个指向数组中第一个元素的常量指针

  • balance 是一个指向 &balance[0] 的指针,即数组 balance 的第一个元素的地址。

    double balance[50];
    
    // 把 p 赋值为 balance 的第一个元素的地址
    
    double *p;
    double balance[10];
    
    p = balance;
    
  • *(balance + 4) 等同于 *(p+4) 即访问 balance[4] 的数据

从函数返回数组

  • C++ 不允许返回一个完整的数组作为函数的参数;可以通过指定不带索引的数组名来返回一个指向数组的指针。

  • 想要从函数返回一个一维数组,您必须声明一个返回指针的函数,如下:

    int * myFunction()
    {
    .
    .
    .
    }
    
  • C++ 不支持在函数外返回局部变量的地址,除非定义局部变量为 static 变量

  • eg:生成 10 个随机数,并使用数组来返回它们

    #include <iostream>
    #include <cstdlib>
    #include <ctime>
    
    using namespace std;
    
    // 要生成和返回随机数的函数
    int * getRandom( )
    {
      static int  r[10];
    
      // 设置种子
      srand( (unsigned)time( NULL ) );
      for (int i = 0; i < 10; ++i)
      {
        r[i] = rand();
        cout << r[i] << endl;
      }
    
      return r;
    }
    
    // 要调用上面定义函数的主函数
    int main ()
    {
       // 一个指向整数的指针
       int *p;
    
       p = getRandom();
       for ( int i = 0; i < 10; i++ )
       {
           cout << "*(p + " << i << ") : ";
           cout << *(p + i) << endl;
       }
    
       return 0;
    }
    

1.17 C++ 字符串

  • C++ 提供了以下两种类型的字符串表示形式:
    • C 风格字符串
    • C++ 引入的 string 类类型

C 风格字符串

  • 字符串实际上是使用 null 字符 ‘\0’ 终止的一维字符数组。

  • 字符数组的大小比实际的字符数多一个。

  • C++ 编译器会在初始化数组时,自动把 ‘\0’ 放在字符串的末尾。

  • 初始化:

    char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
    
    // 或者:
    
    char greeting[] = "Hello";
    
  • 可用函数:

序号函数 & 目的
1strcpy(s1, s2); 复制字符串 s2 到字符串 s1。
2strcat(s1, s2); 连接字符串 s2 到字符串 s1 的末尾。
3strlen(s1); 返回字符串 s1 的长度。(不包括 "\0"
4strcmp(s1, s2); 如果 s1 和 s2 是相同的,则返回 0;如果 s1<s2 则返回值小于 0;如果 s1>s2 则返回值大于 0。
5strchr(s1, ch); 返回一个指针,指向字符串 s1 中 字符 ch 的第一次出现的位置。
6strstr(s1, s2); 返回一个指针,指向字符串 s1 中 字符串 s2 的第一次出现的位置。
  • 示例:

    #include <iostream>
    #include <cstring>
    
    using namespace std;
    
    int main ()
    {
       char str1[11] = "Hello";
       char str2[11] = "World";
       char str3[11];
       int  len ;
    
       // 复制 str1 到 str3
       strcpy( str3, str1);
       cout << "strcpy( str3, str1) : " << str3 << endl;
    
       // 连接 str1 和 str2
       strcat( str1, str2);
       cout << "strcat( str1, str2): " << str1 << endl;
    
       // 连接后,str1 的总长度
       len = strlen(str1);
       cout << "strlen(str1) : " << len << endl;
    
       system("pause");
       return 0;
    }
    
    // strcpy( str3, str1) : Hello
    // strcat( str1, str2): HelloWorld
    // strlen(str1) : 10
    

C++ 中的 String 类

  • C++ 标准库提供了 string 类类型,支持上述所有的操作,另外还增加了其他更多的功能。

  • 示例:

    #include <iostream>
    #include <string>
    
    using namespace std;
    
    int main ()
    {
       string str1 = "Hello";
       string str2 = "World";
       string str3;
       int  len ;
    
       // 复制 str1 到 str3
       str3 = str1;
       cout << "str3 : " << str3 << endl;
    
       // 连接 str1 和 str2
       str3 = str1 + str2;
       cout << "str1 + str2 : " << str3 << endl;
    
       // 连接后,str3 的总长度
       len = str3.size();
       cout << "str3.size() :  " << len << endl;
    
       system("pause");
       return 0;
    }
    
    // str3 : Hello
    // str1 + str2 : HelloWorld
    // str3.size() :  10
    

1.18 C++ 指针

  • 每个变量都有一个内存地址,用 “&” 访问地址。

  • 指针是一个变量,其值为另一个变量的地址,即,内存位置的直接地址。声明:type *name;

  • 所有指针的值的实际数据类型(整型、浮点型、字符型等)都是一样的,都是一个代表内存地址的长的十六进制数。不同数据类型的指针之间唯一的不同是,指针所指向的变量或常量的数据类型不同

  • 示例:

    #include <iostream>
    
    using namespace std;
    
    int main ()
    {
       int  var = 20;   // 实际变量的声明
       int  *ip;        // 指针变量的声明
    
       ip = &var;       // 在指针变量中存储 var 的地址
    
       cout << "Value of var variable: ";
       cout << var << endl;
    
       // 输出在指针变量中存储的地址
       cout << "Address stored in ip variable: ";
       cout << ip << endl;
    
       // 访问指针中地址的值
       cout << "Value of *ip variable: ";
       cout << *ip << endl;
    
       return 0;
    }
    
    // Value of var variable: 20
    // Address stored in ip variable: 0xbfc601ac
    // Value of *ip variable: 20
    
  • C++ 指针详解:

    概念描述
    C++ Null 指针C++ 支持空指针。NULL 指针是一个定义在标准库中的值为零的常量。
    C++ 指针的算术运算可以对指针进行四种算术运算:++、–、+、-
    C++ 指针 vs 数组指针和数组之间有着密切的关系。
    C++ 指针数组可以定义用来存储指针的数组。
    C++ 指向指针的指针C++ 允许指向指针的指针。
    C++ 传递指针给函数通过引用或地址传递参数,使传递的参数在调用函数中被改变。
    C++ 从函数返回指针C++ 允许函数返回指针到局部变量、静态变量和动态内存分配。

空指针

  • 变量声明时,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为指针。

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

    #include <iostream>
    
    using namespace std;
    
    int main ()
    {
       int  *ptr = NULL;
    
       cout << "ptr 的值是 " << ptr ;
    
       return 0;
    }
    // ptr 的值是 0
    
  • 内存地址 0 有特别重要的意义,它表明该指针不指向一个可访问的内存位置。但按照惯例,如果指针包含空值(零值),则假定它不指向任何东西。

  • 因此,如果所有未使用的指针都被赋予空值,同时避免使用空指针,就可以防止误用一个未初始化的指针。很多时候,未初始化的变量存有一些垃圾值,导致程序难以调试。

  • 空指针尽可能的使用 nullptr

指针的算数运算

  • 指针是一个用数值表示的地址。因此,可以对指针执行算术运算。

  • 可以对指针进行四种算术运算:++(指向下一个变量的地址)、–(指向上一个变量的地址)、+、-。

  • 经常用指针代替数组,因为变量指针可以递增,而数组不能递增,因为数组是一个常量指针。示例:

    #include <iostream>
    
    using namespace std;
    const int MAX = 3;
    
    int main ()
    {
       int  var[MAX] = {10, 100, 200};
       int  *ptr;
    
       // 指针指向数组第一个元素地址
       ptr = var;
       // 指针指向数组最后一个地址
       // ptr = &var[MAX-1]
       for (int i = 0; i < MAX; i++)
       {
          cout << "Address of var[" << i << "] = ";
          cout << ptr << endl;
    
          cout << "Value of var[" << i << "] = ";
          cout << *ptr << endl;
    
          // 移动到下一个位置
          ptr++;
          // 移动到上一个位置
          ptr--;
       }
       return 0;
    }
    
  • 指针的比较:

    指针可以用关系运算符进行比较,如 ==、< 和 >。如果 p1 和 p2 指向两个相关的变量,比如同一个数组中的不同元素,则可对 p1 和 p2 进行大小比较。

指针数组

  • 让数组存储指向 int 或 char 或其他数据类型的指针

  • 指向整数的指针数组的声明:int *ptr[MAX];

  • 这里,把 ptr 声明为一个数组,由 MAX 个整数指针组成。因此,ptr 中的每个元素,都是一个指向 int 值的指针。

  • 示例:把三个整数存储在一个指针数组中

    #include <iostream>
    
    using namespace std;
    const int MAX = 3;
    
    int main ()
    {
       int  var[MAX] = {10, 100, 200};
       int *ptr[MAX];
    
       for (int i = 0; i < MAX; i++)
       {
          ptr[i] = &var[i]; // 赋值为整数的地址
       }
       for (int i = 0; i < MAX; i++)
       {
          cout << "Value of var[" << i << "] = ";
          cout << *ptr[i] << endl;
       }
       return 0;
    }
    // Value of var[0] = 10
    // Value of var[1] = 100
    // Value of var[2] = 200
    
  • 指针数组 与 数组指针

    • int *p[n]为指针数组:即存放指针的数组,数组中有n个元素,每个元素为一个int型的指针;
    • int (*p)[n]为数组指针:即指向数组的指针,p为一个指针,指向一个包含n个int元素的数组。
    • 数组和指针,在后面的为主语,前面的是定语,用来修饰主语。

指向指针的指针(多级间接寻址)

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

  • 通常,一个指针包含一个变量的地址。当定义一个指向指针的指针时,第一个指针包含了第二个指针的地址,第二个指针指向包含实际值的位置。

  • 指向指针的指针变量声明:

    int **var;
    
  • 示例:

    #include <iostream>
    
    using namespace std;
    
    int main ()
    {
        int  var;
        int  *ptr;
        int  **pptr;
    
        var = 3000;
    
        // 获取 var 的地址
        ptr = &var;
    
        // 使用运算符 & 获取 ptr 的地址
        pptr = &ptr;
    
        // 使用 pptr 获取值
        cout << "var 值为 :" << var << endl;
        cout << "*ptr 值为:" << *ptr << endl;
        cout << "**pptr 值为:" << **pptr << endl;
    
        return 0;
    }
    // var 值为 :3000
    // *ptr 值为:3000
    // **pptr 值为:3000
    

传递指针给函数

  • 方法:声明函数参数为指针类型

  • 示例:传递一个无符号的 long 型指针给函数

    #include <iostream>
    #include <ctime>
    
    using namespace std;
    void getSeconds(unsigned long *par);
    
    int main ()
    {
       unsigned long sec;
    
    
       getSeconds( &sec );
    
       // 输出实际值
       cout << "Number of seconds :" << sec << endl;
    
       return 0;
    }
    
    void getSeconds(unsigned long *par)
    {
       // 获取当前的秒数
       *par = time( NULL );
       return;
    }
    

传递指针给函数

  • 只需要声明函数参数为指针类型,并将地址传递给函数

  • 示例:传递一个无符号的 long 型指针给函数,并在函数内改变这个值

    #include <iostream>
    #include <ctime>
    
    using namespace std;
    void getSeconds(unsigned long *par);
    
    int main ()
    {
       unsigned long sec;
    
    
       getSeconds( &sec );
    
       // 输出实际值
       cout << "Number of seconds :" << sec << endl;
    
       return 0;
    }
    
    void getSeconds(unsigned long *par)
    {
       // 获取当前的秒数
       *par = time( NULL );
       return;
    }
    
  • 同样,可以将数组传递给函数(能接受指针作为参数的函数,也能接受数组作为参数):

    #include <iostream>
    using namespace std;
    
    // 函数声明
    double getAverage(int *arr, int size);
    
    int main ()
    {
       // 带有 5 个元素的整型数组
       int balance[5] = {1000, 2, 3, 17, 50};
       double avg;
    
       // 传递一个指向数组的指针作为参数
       avg = getAverage( balance, 5 ) ;
    
       // 输出返回值
       cout << "Average value is: " << avg << endl; 
    
       return 0;
    }
    
    double getAverage(int *arr, int size)
    {
      int    i, sum = 0;       
      double avg;          
    
      for (i = 0; i < size; ++i)
      {
        sum += arr[i];
       }
    
      avg = double(sum) / size;
    
      return avg;
    }
    // Average value is: 214.4
    

从函数返回指针

  • 首先声明一个返回指针的函数:(C++ 不支持在函数外返回局部变量的地址,除非定义局部变量为 static 变量。)

    int * myFunction()
    {
    .
    .
    .
    }
    
  • 示例:

    #include <iostream>
    #include <ctime>
    #include <cstdlib>
    
    using namespace std;
    
    // 要生成和返回随机数的函数
    int * getRandom( )
    {
      static int  r[10];
    
      // 设置种子
      srand( (unsigned)time( NULL ) );
      for (int i = 0; i < 10; ++i)
      {
        r[i] = rand();
        cout << r[i] << endl;
      }
    
      return r;
    }
    
    // 要调用上面定义函数的主函数
    int main ()
    {
       // 一个指向整数的指针
       int *p;
    
       p = getRandom();
       for ( int i = 0; i < 10; i++ )
       {
           cout << "*(p + " << i << ") : ";
           cout << *(p + i) << endl;
       }
    
       return 0;
    }
    

1.19 C++ 引用

  • 引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字。
  • 一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量。

引用 vs 指针

区别:

  • 不存在空引用。引用必须连接到一块合法的内存。
  • 一旦引用被初始化为一个对象,就不能被指向到另一个对象。指针可以在任何时候指向到另一个对象。
  • 引用必须在创建时被初始化。指针可以在任何时间被初始化。
  • 引用不占内存,但指针是一个变量,是有自己的独立内存空间的

创建引用

  • 变量名称是变量附属在内存位置中的标签,引用相当于是变量附属在内存位置中的第二个标签。可以通过原始变量名称或引用来访问变量的内容。

  • 示例:

    #include <iostream>
    
    using namespace std;
    
    int main ()
    {
       // 声明简单的变量
       int    i;
       double d;
    
       // 声明引用变量
       int&    r = i;
       double& s = d;
    
       i = 5;
       cout << "Value of i : " << i << endl;
       cout << "Value of i reference : " << r  << endl;
    
       d = 11.7;
       cout << "Value of d : " << d << endl;
       cout << "Value of d reference : " << s  << endl;
    
       return 0;
    }
    // Value of i : 5
    // Value of i reference : 5
    // Value of d : 11.7
    // Value of d reference : 11.7
    
  • 引用通常用于函数参数列表和函数返回值。

引用作为参数

#include <iostream>
using namespace std;

// 函数声明
void swap(int& x, int& y);

int main ()
{
   // 局部变量声明
   int a = 100;
   int b = 200;

   cout << "交换前,a 的值:" << a << endl;
   cout << "交换前,b 的值:" << b << endl;

   /* 调用函数来交换值 */
   swap(a, b);

   cout << "交换后,a 的值:" << a << endl;
   cout << "交换后,b 的值:" << b << endl;

   return 0;
}

// 函数定义
void swap(int& x, int& y)
{
   int temp;
   temp = x; /* 保存地址 x 的值 */
   x = y;    /* 把 y 赋值给 x */
   y = temp; /* 把 x 赋值给 y  */

   return;
}
// 交换前,a 的值: 100
// 交换前,b 的值: 200
// 交换后,a 的值: 200
// 交换后,b 的值: 100

引用作为返回值

  • 通过使用引用来替代指针,会使 C++ 程序更容易阅读和维护。函数返回一个引用的方式与返回一个指针类似。

  • 当函数返回一个引用时,则返回一个指向返回值的隐式指针。这样,函数就可以放在赋值语句的左边。

  • 示例:

    #include <iostream>
    
    using namespace std;
    
    double vals[] = {10.1, 12.6, 33.1, 24.1, 50.0};
    
    double& setValues( int i )
    {
      return vals[i];   // 返回第 i 个元素的引用
    }
    
    // 要调用上面定义函数的主函数
    int main ()
    {
    
       cout << "改变前的值" << endl;
       for ( int i = 0; i < 5; i++ )
       {
           cout << "vals[" << i << "] = ";
           cout << vals[i] << endl;
       }
    
       setValues(1) = 20.23; // 改变第 2 个元素
       setValues(3) = 70.8;  // 改变第 4 个元素
    
       cout << "改变后的值" << endl;
       for ( int i = 0; i < 5; i++ )
       {
           cout << "vals[" << i << "] = ";
           cout << vals[i] << endl;
       }
       return 0;
    }
    
  • 当返回一个引用时,被引用的对象不能超出作用域。返回一个对局部变量的引用是不合法的,但是,可以返回一个对静态变量的引用。

    int& func() {
       int q;
       // return q; // 在编译时发生错误
       static int x;
       return x;     // 安全,x 在函数作用域外依然是有效的
    }
    

1.20 C++ 日期 & 时间

  • C++ 继承了 C 语言用于日期和时间操作的结构和函数。为了使用日期和时间相关的函数和结构,需要在 C++ 程序中引用 <ctime> 头文件。

  • 有四个与时间相关的类型:clock_t、time_t、size_ttm。类型 clock_t、size_t 和 time_t 能够把系统时间和日期表示为某种整数。

    结构类型 tm 把日期和时间以 C 结构的形式保存,tm 结构的定义如下:

    struct tm {
      int tm_sec;   // 秒,正常范围从 0 到 59,但允许至 61
      int tm_min;   // 分,范围从 0 到 59
      int tm_hour;  // 小时,范围从 0 到 23
      int tm_mday;  // 一月中的第几天,范围从 1 到 31
      int tm_mon;   // 月,范围从 0 到 11
      int tm_year;  // 自 1900 年起的年数
      int tm_wday;  // 一周中的第几天,范围从 0 到 6,从星期日算起
      int tm_yday;  // 一年中的第几天,范围从 0 到 365,从 1 月 1 日算起
      int tm_isdst; // 夏令时
    }
    
  • 函数:

    序号函数 & 描述
    1time_t time(time_t *time); 该函数返回系统的当前日历时间,自 1970 年 1 月 1 日以来经过的秒数。如果系统没有时间,则返回 .1。
    2char *ctime(const time_t *time); 该返回一个表示当地时间的字符串指针,字符串形式 day month year hours:minutes:seconds year\n\0
    3struct tm *localtime(const time_t *time); 该函数返回一个指向表示本地时间的 tm 结构的指针。
    4clock_t clock(void); 该函数返回程序执行起(一般为程序的开头),处理器时钟所使用的时间。如果时间不可用,则返回 .1。
    5char * asctime ( const struct tm * time ); 该函数返回一个指向字符串的指针,字符串包含了 time 所指向结构中存储的信息,返回形式为:day month date hours:minutes:seconds year\n\0。
    6struct tm *gmtime(const time_t *time); 该函数返回一个指向 time 的指针,time 为 tm 结构,用协调世界时(UTC)也被称为格林尼治标准时间(GMT)表示。
    7time_t mktime(struct tm *time); 该函数返回日历时间,相当于 time 所指向结构中存储的时间。
    8double difftime ( time_t time2, time_t time1 ); 该函数返回 time1 和 time2 之间相差的秒数。
    9size_t strftime(); 该函数可用于格式化日期和时间为指定的格式。
  • 参考:C/C++时间函数的用法 (vcsos.com)

1.21 C++ 基本输入输出

  • C++ 的 I/O 发生在流中,流是字节序列。
    • 如果字节流是从设备(如键盘、磁盘驱动器、网络连接等)流向内存,这叫做输入操作
    • 如果字节流是从内存流向设备(如显示屏、打印机、磁盘驱动器、网络连接等),这叫做输出操作

I/O 库头文件

头文件函数和描述
<iostream>该文件定义了 cin、cout、cerrclog 对象,分别对应于标准输入流、标准输出流、非缓冲标准错误流和缓冲标准错误流。
<iomanip>该文件通过所谓的参数化的流操纵器(比如 setwsetprecision),来声明对执行标准化 I/O 有用的服务。
<fstream>该文件为用户控制的文件处理声明服务。我们将在文件和流的相关章节讨论它的细节。

标准输出流(cout)

  • 预定义的对象 coutiostream 类的一个实例。cout 对象"连接"到标准输出设备,通常是显示屏。cout 是与流插入运算符 << 结合使用的。
  • cout << "Value of str is : " << 变量名 << endl;

标准输入流(cin)

  • 预定义的对象 ciniostream 类的一个实例。cin 对象附属到标准输入设备,通常是键盘。cin 是与流提取运算符 >> 结合使用的,如下所示:
  • cin >> name
  • 流提取运算符 >> 在一个语句中可以多次使用,如果要求输入多个数据,可以使用如下语句:cin >> name >> age;

标准错误流(cerr)

  • 预定义的对象 cerriostream 类的一个实例。cerr 对象附属到标准错误设备,通常也是显示屏,但是 cerr 对象是非缓冲的,且每个流插入到 cerr 都会立即输出。

  • cerr 也是与流插入运算符 << 结合使用的,示例:

    #include <iostream>
    
    using namespace std;
    
    int main( )
    {
       char str[] = "Unable to read....";
    
       cerr << "Error message : " << str << endl;
    }
    // Error message : Unable to read....
    

标准日志流(clog)

  • 预定义的对象 clogiostream 类的一个实例。clog 对象附属到标准错误设备,通常也是显示屏,但是 clog 对象是缓冲的。这意味着每个流插入到 clog 都会先存储在缓冲区,直到缓冲填满或者缓冲区刷新时才会输出。

  • clog 也是与流插入运算符 << 结合使用的,如下所示:

    #include <iostream>
    
    using namespace std;
    
    int main( )
    {
       char str[] = "Unable to read....";
    
       clog << "Error message : " << str << endl;
    }
    // Error message : Unable to read....
    

1.22 C++ 结构体

  • 结构体允许存储不同类型的数据项

  • 定义:

    struct type_name {
       member_type1 member_name1;
       member_type2 member_name2;
       member_type3 member_name3;
       .
       .
    } object_names;
    
  • 访问结构成员

    • 使用成员访问运算符(.)
  • 结构体可以作为函数参数

  • 指向结构体的指针:

    struct Books *struct_pointer;
    

    使用指向该结构的指针访问结构的成员,使用 -> 运算符

  • typedef 关键字

    • 为创建的结构体起“别名”:直接使用 Books 来定义 Books 类型的变量,不需要使用 struct 关键字。

      typedef struct Books
      {
         char  title[50];
         char  author[50];
         char  subject[100];
         int   book_id;
      }Books;
      
      // 使用:
      Books Book1, Book2;
      
    • 也可以定义非结构体类型: x, y 和 z 都是指向长整型 long int 的指针。

      typedef long int *pint32;
      
      pint32 x, y, z;
      
    • typedef 与 #define 的区别:

      • typedef 仅限于为类型定义符号名称,#define 不仅可以为类型定义别名,也能为数值定义别名,比如您可以定义 1 为 ONE。
      • typedef 是由编译器执行解释的,#define 语句是由预编译器进行处理的。

参考:

  • https://www.nowcoder.com/tutorial/10003/726e8520c91b40d8b26e2d9f8880b9e1
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 学习(基础语法篇) 的相关文章

随机推荐

  • 课设-基于51单片机+超声波模块的避障小车(源码+原理图+Protel仿真)

    基于51单片机 43 超声波模块的避障小车 xff08 源码 43 原理图 43 Protel仿真 xff09 一 功能二 模块2 1 电机驱动模块2 2 超声波模块 三 程序代码四 PCB原理图 一 功能 设计一辆利用超声波传感器来实现避
  • 路径规划(一):使用Matlab快速绘制栅格地图

    目录 一 Matlab快速绘制栅格地图1 几种常用的地图形式 xff1a 1 1 尺度地图 xff1a 1 2 拓扑地图 xff1a 1 3 语义地图 xff1a 2 栅格地图用于路径规划的优势 xff1a 3 matlab绘制栅格地图的核
  • 2、无人驾驶--路径规划算法:Dijkstra

    目录 2 Dijkstra2 1 算法简介2 2 算法思路具体流程 xff1a 2 3 算法具体实现2 3 1 程序详解 2 Dijkstra 声明 xff1a 本文是学习古月居 基于栅格地图的机器人路径规划算法指南 黎万洪 后写的笔记 x
  • 毕设--基于51单片机的温度报警器设计

    目录 1 简介2 设计要求与方案论证2 1 设计要求2 2 系统基本方案选择和论证2 2 1 单片机芯片的选择方案和论证2 2 2 温度传感器设计方案论证 2 3 电路设计最终方案决定 3 硬件设计介绍3 1 STC89C51介绍3 1 1
  • 基于51单片机的篮球比赛计时器

    目录 基于51单片机的篮球比赛计时器1 PCB原理图2 仿真图3 毕设要求 xff1a 4 总体方案设计5 程序源码6 资源下载 基于51单片机的篮球比赛计时器 注 xff1a 本毕设资源可在微信公众号 xff1a Kevin的学习站 中获
  • 毕设--基于51单片机数字电压表的设计

    目录 基于51单片机数字电压表的设计1 PCB原理图2 Proteus 仿真图3 设计目标3 1 基本功能3 2 主要技术参数 4 总设计框图5 硬件设计分析5 1 电源的设计5 2 单片机最小系统5 3 模数转换 6 软件设计的组成7 元
  • 基于51单片机的智能温控风扇(程序+仿真+原理图)

    目录 基于51单片机的智能温控风扇1 主要功能2 实验结果3 仿真工程4 原理图5 程序源码6 资源获取 基于51单片机的智能温控风扇 1 主要功能 基于51单片机的智能温控风扇 xff0c 通过DS180温度传感器采集温度 xff0c 并
  • 基于51单片机的八路竞赛抢答器设计

    目录 基于51单片机的八路抢答器设计1 主要功能2 仿真图3 测试图4 程序源码5 资源获取 基于51单片机的八路抢答器设计 1 主要功能 利用STC89C52单片机及外围接口实现的抢答系统 xff1b 在抢答过程中 xff0c 只有启动抢
  • 赛灵思-Zynq UltraScale+ MPSoC学习笔记汇总

    Zynq UltraScale 43 MPSoC学习目录 xff1a 1 赛灵思 Zynq UltraScale 43 MPSoCs xff1a 产品简介 2 赛灵思 Zynq UltraScale 43 MPSoC学习笔记 xff1a P
  • 数据可视化--实验五:高维非空间数据可视化

    声明 xff1a 本文CSDN作者原创投稿文章 xff0c 未经许可禁止任何形式的转载 xff0c 原文链接 文章目录 概要实验过程Pyecharts实验结果平行坐标系room1 6房间人员时长饼图 概要 学院 xff1a 计算机科学与技术
  • 7、AUTOSAR MCAL入门-实战:I/O驱动组

    7 AUTOSAR MCAL入门 实战 xff1a I O驱动组 在第三节中有介绍AUTOSAR 把MCAL 抽象分为4个驱动组 xff0c 分别为 xff1a 微控制器驱动组 xff0c 存储器驱动组 xff0c 通信驱动组 输入 输出驱
  • FreeRTOS学习笔记:FreeRTOS启动方式及流程

    FreeRTOS启动方式及流程 FreeRTOS有两种比较流行的启动方式 1 方式一 xff1a 在main函数中创建所有任务 具体说明 xff1a 在main函数中将硬件初始化 RTOS系统初始化 xff0c 创建所有的任务 xff0c
  • 树莓派4B与Android之缘——树莓派下LineageOS(Android 9)系统开机联网与远程控制

    一 树莓派连接屏幕 1 找到树莓派的micro hdmi口 xff0c 是视频图像的输出口 xff0c 见下图中的MICRO HDMI PORTS 2 连接屏幕 xff08 1 xff09 如果显示屏输入端口是HDMI xff0c 就用mi
  • Deep SDF 、NeuS学习

    DeepSDF Learning Continuous Signed Distance Functions for Shape Representation xff1a 学习用于形状表示的连续有符号距离函数 NeuS Learning Ne
  • layui 引入方式

    layui xff08 谐音 xff1a 类UI 是一款采用自身模块规范编写的前端 UI 框架 xff0c 遵循原生 HTML CSS JS 的书写与组织形式 xff0c 门槛极低 xff0c 拿来即用 其外在极简 xff0c 却又不失饱满
  • ubuntu20.04安装ROS及常见问题

    ubuntu20 04安装ROS及常见问题 一 ubuntu安装参考 xff08 双系统 xff09 1 ios镜像官网下载地址 xff1a https releases ubuntu com ga 61 2 239339907 18418
  • 在jetson xavier nx上配置orbslam3,带稠密重建

    这里写自定义目录标题 主要记录一下踩过的各种坑 xff0c 包括从配置开发板系统到配置orbslam3一条龙服务 xff0c 带cuda加速的opencv3 4 5开发板刷系统将系统移植到M 2硬盘上Sdkmanager安装cuda cud
  • ROS入门教程(五)—— RViz仿真

    上篇文章我们介绍了URDF文件的导出 xff0c 本文将继上文介绍安装完导出URDF文件后 xff0c 如何在机器人操作系统 ROS 中显示 xff0c 并且让它动起来 目录 前言 RViz机器人模型可视化 launch启动RViz配置文件
  • js几种继承

    提示 xff1a 主要是原型链继承 构造函数继承 原型链加构造函数继承 寄生组合式继承 一 原型链继承 子类想要继承父类的属性和方法 xff0c 可以将其原型对象指向父类的实例 xff0c 根据原型链就可以使用到父类的方法和属性 父类 fu
  • C++ 学习(基础语法篇)

    一 基础语法 1 1 C 43 43 简介 C 43 43 是一种静态类型的 编译式的 通用的 大小写敏感的 不规则的编程语言 xff0c 支持过程化编程 面向对象编程和泛型编程 C 43 43 是 C 的一个超集 xff0c 事实上 xf