北京大学c++程序设计听课笔记101

news2024/11/16 20:08:53

c2827f0432044b2f9c33eb2c206673ac.png

基本概念
程序运行期间,每个函数都会占用一段连续的内存空间。而函数名就是该函数所占内存区域的起始地址(也称“入口地址”)。我们可以将函数的入口地址赋给一个指针变量,使该指针变量指向该函数。然后通过指针变量就可以调用这个函数。这种指向函数的指针变量称为“函数指针”。

### 预习:有趣的故事引入

在一个风和日丽的早晨,你走进了计算机科学课的教室,发现桌上放着一张神秘的地图,上面画满了各种指针和箭头。你的任务是解开这张地图的秘密,揭示指针在C++编程中的奥秘。你准备好了吗?让我们开始这场探险吧!

### 问题拆解与引导

#### 问题1:什么是指针,为什么在C++中重要?

**推导思路:**
- **定义理解**:首先,理解指针(Pointer)是什么——它是一个变量,用于存储另一个变量的内存地址。
- **重要性分析**:讨论指针在内存管理、数组操作、函数参数传递等方面的重要性。

**解答与例子:**
- 指针允许直接操作内存,提高程序的灵活性和效率。
- 例如,在函数中传递大数据结构时,可以通过指针避免不必要的复制,提高性能。

```cpp
#include <iostream>

void increment(int* ptr) {
    (*ptr)++;
}

int main() {
    int num = 10;
    increment(&num);
    std::cout << "Incremented num: " << num << std::endl; // 输出11
}
```

在这个例子中,通过指针传递变量地址,实现对原始数据的修改。

### 1. 这是什么语言?

这段代码是用C++编写的。

### 2. 逐行语法结构和函数用法说明

```cpp
#include <iostream>
```
- **语法结构**:这是一个预处理指令,用于包含标准输入输出流库。
- **先修知识**:了解C++标准库的作用和使用`#include`指令。

```cpp
void increment(int* ptr) {
    (*ptr)++;
}
```
- **语法结构**:
  - `void`:函数返回类型,表示该函数不返回任何值。
  - `increment`:函数名。
  - `(int* ptr)`:函数参数,`int*`表示参数是一个指向整数的指针。
  - `{}`:函数体,包含需要执行的代码。
  - `(*ptr)++`:解引用指针`ptr`获取其指向的整数值,然后自增。
- **先修知识**:了解指针的概念和使用方法,解引用操作符`*`,以及自增操作符`++`。

```cpp
int main() {
```
- **语法结构**:
  - `int`:函数返回类型,表示返回一个整数。
  - `main`:主函数名,是程序的入口点。
  - `()`:表示函数没有参数。
- **先修知识**:了解C++程序的执行入口是`main`函数。

```cpp
    int num = 10;
```
- **语法结构**:
  - `int`:整数类型。
  - `num`:变量名。
  - `=`:赋值操作符。
  - `10`:整数值。
- **先修知识**:变量声明和初始化。

```cpp
    increment(&num);
```
- **语法结构**:
  - `increment`:函数调用。
  - `&num`:取地址操作符,获取变量`num`的内存地址。
- **先修知识**:函数调用和取地址操作。

```cpp
    std::cout << "Incremented num: " << num << std::endl;
```
- **语法结构**:
  - `std::cout`:标准输出流对象,用于输出数据到控制台。
  - `<<`:插入操作符,将数据插入输出流。
  - `"Incremented num: "`:字符串常量。
  - `num`:变量输出。
  - `std::endl`:流操纵符,用于输出换行符并刷新缓冲区。
- **先修知识**:输入输出流操作。

### 3. 分类举例说明这个代码用来做什么?

- **应用场景**:这段代码展示了如何通过指针参数修改函数外部变量的值。
- **举例说明**:
  - **数据处理**:在复杂算法中,需要通过函数修改数组或对象的值时,可以使用指针传递。
  - **性能优化**:通过指针传递大型数据结构可以避免不必要的复制,提高性能。

### 4. 设计一道类似作用的代码题

**题目**:编写一个函数`swap`,用于交换两个整数的值。要求使用指针作为函数参数,并在主函数中验证交换结果。

**思路说明**:
1. 创建一个`swap`函数,接收两个整数指针。
2. 在`swap`函数中,使用一个临时变量交换两个指针所指向的整数值。
3. 在`main`函数中,定义两个整数并调用`swap`函数,输出交换后的结果。

**带逐行注释的代码**:

```cpp
#include <iostream>

// 定义swap函数,接收两个整数指针
void swap(int* a, int* b) {
    int temp = *a; // 用临时变量存储a指向的值
    *a = *b;       // 将b指向的值赋给a指向的位置
    *b = temp;     // 将临时变量的值赋给b指向的位置
}

int main() {
    int x = 5; // 定义整数x,并初始化为5
    int y = 10; // 定义整数y,并初始化为10

    std::cout << "Before swap: x = " << x << ", y = " << y << std::endl;

    swap(&x, &y); // 调用swap函数,交换x和y的值

    std::cout << "After swap: x = " << x << ", y = " << y << std::endl; // 输出交换后的结果

    return 0;
}
```

**解释**:
- 函数`swap`接受两个指针参数,通过解引用修改实际存储位置的值,实现交换。
- 在`main`函数中,使用取地址符`&`传递整数`x`和`y`的地址给`swap`函数。
- 程序输出交换前后的结果,验证函数的正确性。

#### 问题2:如何使用指针来创建和遍历链表?

**推导思路:**
- **链表结构理解**:了解链表(Linked List)是一种动态数据结构,由节点组成,每个节点包含数据和指向下一个节点的指针。
- **基本操作**:学习如何创建节点、连接节点、遍历链表。

**解答与例子:**
- 使用指针可以动态地分配内存,创建链表节点,并灵活地改变链表结构。

```cpp
#include <iostream>

struct Node {
    int data;
    Node* next;
};

int main() {
    Node* head = new Node{1, nullptr};
    head->next = new Node{2, nullptr};
    head->next->next = new Node{3, nullptr};

    Node* current = head;
    while (current != nullptr) {
        std::cout << current->data << " ";
        current = current->next;
    }
    std::cout << std::endl;

    // 清理内存
    while (head != nullptr) {
        Node* temp = head;
        head = head->next;
        delete temp;
    }
}
```

在这个例子中,创建了一个简单的链表并遍历输出每个节点的值。

### 思维导图总结

1. **指针基础**
   - 定义与用途
   - 内存地址操作

2. **指针应用**
   - 指针与数组
   - 指针与函数
   - 指针与动态数据结构(链表、树)

3. **指针管理**
   - 内存分配与释放
   - 智能指针(`std::unique_ptr`、`std::shared_ptr`)

### 思考题

#### 题1:为什么使用指针可以提高程序的效率?请从内存管理和数据传递的角度分析。

**答案:**
- **内存管理**:指针允许动态分配内存,仅在需要时分配,减少不必要的内存占用。
- **数据传递**:通过指针传递大数据结构时,只需要传递地址,避免了复制整个数据,提高了效率。

#### 题2:在链表的实现中,为什么需要小心处理内存释放?

**答案:**
- 在链表使用过程中,每个节点使用`new`操作符动态分配内存。为了避免内存泄漏,程序结束或节点不再需要时,应使用`delete`操作符释放内存。

【课堂学习】

INTJ学生:老师,我对函数指针有些困惑。能否详细阐述一下它的基本概念和应用?

ENTP老师:当然可以!函数指针是C和C++中一个非常强大的特性,它允许我们通过指针来调用函数。这种技术可以用于编写更灵活和通用的代码。让我们一步步来理解。

### 函数指针的基本概念

1. **函数的内存表示**:
   - 每个函数在程序运行时都会占用一段连续的内存空间,函数名就是该内存段的起始地址,也称为函数的“入口地址”(Entry Address)。

2. **函数指针的定义**:
   - 函数指针是一个变量,它存储的是函数的入口地址。通过这个指针,我们可以调用指针所指向的函数。

3. **定义函数指针**:
   - 定义函数指针的语法类似于函数声明,只不过在函数名的位置用一个指针变量来代替。

### 具体例子

假设我们有一个简单的函数,它执行两个整数的加法:

```cpp
#include <iostream>

// 定义一个简单的加法函数
int add(int a, int b) {
    return a + b;
}

int main() {
    // 定义一个函数指针,指向返回类型为int,参数为两个int的函数
    int (*funcPtr)(int, int);

    // 将加法函数的地址赋给函数指针
    funcPtr = add;

    // 使用函数指针调用函数
    int result = funcPtr(5, 3);

    std::cout << "Result of add(5, 3): " << result << std::endl;

    return 0;
}
```

### 逐行解释

1. **`int add(int a, int b)`**:
   - 这是一个简单的函数,接收两个整数并返回它们的和。

2. **`int (*funcPtr)(int, int);`**:
   - 这里定义了一个函数指针`funcPtr`。它指向一个返回类型为`int`,参数类型为两个`int`的函数。

3. **`funcPtr = add;`**:
   - 将函数`add`的地址赋给函数指针`funcPtr`。现在`funcPtr`指向`add`函数。

4. **`int result = funcPtr(5, 3);`**:
   - 使用函数指针`funcPtr`调用`add`函数,并将结果存储在`result`中。

5. **输出结果**:
   - `std::cout << "Result of add(5, 3): " << result << std::endl;`输出调用结果,显示为8。

### 函数指针的应用场景

1. **回调函数(Callback Functions)**:
   - 在某些库或框架中,允许用户提供自定义的函数来在特定事件发生时调用。

2. **实现函数表(Function Table)或命令模式**:
   - 在需要动态选择和调用函数的情况下,比如实现菜单选项或命令执行。

3. **简化复杂系统的模块化**:
   - 在一些大型系统中,函数指针可以用来调用不同模块中的函数,实现模块间的解耦。

通过函数指针,我们可以使程序更加灵活和模块化。

INTJ学生:老师,我对指针在计算机组成原理中的角色也很感兴趣。能否解释一下?

ENTP老师:当然!指针在计算机科学中是一个非常重要的概念,它与计算机的内存管理和程序执行息息相关。让我们从计算机组成原理的角度来分析指针的工作机制。

### 内存与指针

1. **内存结构**:
   - 计算机内存是一个线性地址空间,每个内存单元都有一个唯一的地址(Address)。在大多数计算机中,内存是通过字节(Byte)来组织的,每个字节有一个地址。

2. **指针的本质**:
   - 指针是一个变量,它存储的是内存地址。通过指针,我们可以直接访问和操作内存中的数据。

3. **指针的类型**:
   - 指针的类型决定了指针在解引用(Dereference)时访问的内存数据的类型和大小。例如,`int*`指针通常指向一个4字节的整数数据。

### 指针与CPU

1. **寄存器与地址计算**:
   - CPU中有专门的寄存器用于存储内存地址,例如程序计数器(Program Counter, PC)和栈指针(Stack Pointer, SP)。
   - 指针操作通常涉及地址计算,比如指针加减运算,这需要CPU计算出正确的内存地址。

2. **指令执行**:
   - 大多数CPU指令集支持基于指针的操作,如加载(Load)和存储(Store)指令,这些指令使用指针来访问内存。

### 指针与程序执行

1. **栈(Stack)和堆(Heap)内存管理**:
   - 栈内存用于存储函数调用信息和局部变量,栈指针(SP)用于指示当前栈顶的位置。
   - 堆内存用于动态分配内存,指针用于管理这些动态分配的内存块。

2. **函数调用与返回**:
   - 指针在函数调用过程中用于保存返回地址,使得程序可以在函数执行完毕后返回到正确的代码位置。

### 指针操作的低级实现

1. **指针运算**:
   - 当进行指针加减操作时,实际上是对地址进行加减运算。例如,`ptr + 1`不是简单地增加1,而是增加一个数据类型大小的偏移量。

2. **指针的解引用**:
   - 解引用指针意味着访问指针所指向的内存地址上的数据。CPU通过加载指令,将该地址的数据读入寄存器中。

3. **内存对齐(Alignment)**:
   - 为了提高访问效率,数据通常按其大小对齐存储在内存中。例如,32位整数通常存储在4字节对齐的地址上。

### 实际应用场景

1. **数据结构实现**:
   - 链表、树等数据结构都依赖指针来链接各个节点。

2. **系统编程**:
   - 操作系统中广泛使用指针来管理进程内存空间、文件描述符等资源。

通过这些机制,指针在计算机组成原理中扮演了至关重要的角色,为程序的高效执行和内存的灵活管理提供了基础。

【案例故事】

小明是一名经验丰富的C++程序员,他每天都在与各种各样的代码打交道。但有一天,他突然被一个问题困住了:为什么指针在C++中如此重要?为了寻找答案,小明决定深入计算机的内部世界,探索指针的奥秘。

### 探索指针的世界

在一个阳光明媚的周末,小明坐在电脑前,开始编写一个简单的程序。他定义了一个整数和一个指向它的指针:

```cpp
#include <iostream>

int main() {
    int num = 42; // 定义一个整数
    int* ptr = &num; // 定义一个指针,指向整数的地址

    std::cout << "num的值: " << num << std::endl;
    std::cout << "ptr指针指向的地址: " << ptr << std::endl;
    std::cout << "通过ptr访问num的值: " << *ptr << std::endl;

    return 0;
}
```

小明通过这段代码,明白了指针的基本作用:它是一个变量,存储了另一个变量的内存地址。运行程序时,他看到`num`的值为42,`ptr`存储的是`num`的内存地址,解引用(dereference)`ptr`后又得到了42。

### 内存的神秘之旅

小明的好奇心被激发了,他想象自己进入了计算机的内存世界。内存就像一座巨大的城市,每个地址都是一栋独立的房子,而指针就是这座城市的地图,帮助他找到并访问每个房子里的内容。

他意识到,通过指针,他可以对这座城市进行高效的导航和操作。例如,他可以轻松地改变一个地址上存储的值:

```cpp
*ptr = 100; // 通过指针改变num的值
std::cout << "改变后的num的值: " << num << std::endl;
```

小明惊讶地发现,尽管他没有直接操作变量`num`,但通过指针`ptr`,他成功地改变了`num`的值。这种能力让他感受到指针的强大力量。

### 探索更深的技术细节

随着对指针的了解加深,小明开始思考指针在更复杂的数据结构中的应用,比如链表和树。他写了一段简单的链表代码,进一步理解指针的灵活性:

```cpp
#include <iostream>

struct Node {
    int data;
    Node* next;
};

int main() {
    Node* head = new Node(); // 创建第一个节点
    head->data = 1;
    head->next = new Node(); // 创建第二个节点
    head->next->data = 2;
    head->next->next = nullptr; // 链表结束

    // 遍历链表
    Node* current = head;
    while (current != nullptr) {
        std::cout << "节点值: " << current->data << std::endl;
        current = current->next;
    }

    // 释放内存
    delete head->next;
    delete head;

    return 0;
}
```

通过这段代码,小明理解了如何使用指针来动态管理内存和构建灵活的数据结构。链表中的每个节点都通过指针连接,形成一个可以动态扩展的结构。

### 思辨与讨论

小明开始思考:指针为何如此重要?他意识到,指针不仅仅是访问内存的工具,更是实现复杂数据结构和算法的基础。在操作系统中,指针被广泛用于管理内存和资源;在应用程序中,指针用于实现高效的数据传输和处理。

然而,小明也意识到指针带来的潜在危险。错误的指针操作可能导致内存泄漏、悬挂指针(dangling pointer)等问题。因此,理解和谨慎使用指针是每个程序员必备的技能。

以下是一套针对指针及其相关知识的复习题,以及详细解答。这些题目涵盖了指针的基本概念、应用、技术处理和项目管理等多个方面。

### 选择题

1. **情景**:小明正在调试一个C++程序,发现程序在访问某个数组元素时崩溃了。经过检查,他发现使用了一个未初始化的指针。
   - **问题**:未初始化指针可能导致哪种问题?
     - A) 内存泄漏
     - B) 悬挂指针(Dangling Pointer)
     - C) 访问非法内存
     - D) 程序效率低下

   **解答**:C) 访问非法内存。未初始化指针指向一个不确定的内存地址,访问它可能导致程序崩溃。

2. **情景**:在一个需要频繁动态分配和释放内存的程序中,使用智能指针(Smart Pointer)来管理内存。
   - **问题**:以下哪种智能指针会自动释放不再使用的对象?
     - A) `std::unique_ptr`
     - B) `std::shared_ptr`
     - C) `std::weak_ptr`
     - D) 以上全部

   **解答**:D) 以上全部。`std::unique_ptr`和`std::shared_ptr`会自动管理内存的释放,而`std::weak_ptr`用于避免循环引用。

### 判断题

3. **情景**:在一个链表实现中,小明决定用一个临时指针遍历链表。
   - **问题**:使用临时指针遍历链表时,不需要担心修改链表的结构。(判断正误)

   **解答**:正确。遍历操作只涉及读取链表节点的数据,不会改变链表的结构。

4. **情景**:在使用函数指针时,必须确保指针指向一个有效且正确类型的函数。
   - **问题**:如果函数指针指向一个错误类型的函数,仍然可以正常调用。(判断正误)

   **解答**:错误。函数指针必须指向正确类型的函数,否则会导致未定义行为。

### 分析题

5. **情景**:小明正在优化一个多线程应用程序,该程序偶尔会崩溃。
   - **问题**:分析可能的原因,并给出解决方案。

   **解答**:崩溃可能是由于多个线程同时访问共享资源导致的竞争条件(Race Condition)。解决方案包括:
   - 使用互斥锁(Mutex)来保护共享资源。
   - 使用原子操作(Atomic Operation)来确保数据一致性。
   - 考虑使用线程安全的数据结构。

### 代码分析题

6. **情景**:以下是一段实现简单链表的代码:
   ```cpp
   #include <iostream>
   
   struct Node {
       int data;
       Node* next;
   };

   void printList(Node* head) {
       Node* current = head;
       while (current != nullptr) {
           std::cout << current->data << " ";
           current = current->next;
       }
       std::cout << std::endl;
   }

   int main() {
       Node* head = new Node{1, nullptr};
       head->next = new Node{2, nullptr};
       head->next->next = new Node{3, nullptr};

       printList(head);

       // Memory leak problem
       return 0;
   }
   ```
   - **问题**:找出代码中的问题并改正。

   **解答**:代码中存在内存泄漏问题,因为分配的内存没有被释放。可以在程序结束前加入释放内存的代码:
   ```cpp
   Node* current = head;
   while (current != nullptr) {
       Node* next = current->next;
       delete current;
       current = next;
   }
   ```

### 案例技术处理

7. **情景**:在一个大型项目中,团队需要处理大量的文件I/O操作,使用指针管理文件数据。
   - **问题**:如何确保文件指针操作的安全性和效率?

   **解答**:
   - 确保所有文件指针在使用前都已正确打开,并在使用后及时关闭。
   - 使用RAII(资源获取即初始化)模式,例如C++中的文件流类,自动管理文件指针的生命周期。
   - 实施错误检查机制,确保文件操作失败时能够正确处理。

### 项目工程管理和团队合作细节论述题

8. **情景**:团队正在开发一个需要高效内存管理的实时系统。
   - **问题**:如何在项目工程管理中优化内存管理,并促进团队合作?

   **解答**:
   - **项目工程管理**:
     - 制定明确的内存管理策略,包括使用智能指针、内存池等技术。
     - 进行代码审查,确保所有指针操作符合最佳实践。
     - 使用工具进行静态和动态分析,检测内存泄漏和非法访问。
   - **团队合作**:
     - 定期举行技术讨论会,分享内存管理经验和最佳实践。
     - 提供培训,提升团队成员的内存管理能力。
     - 实施代码协作工具,确保团队成员能够高效地进行代码合并和冲突解决。

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2241720.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(时序论文阅读)TimeMixer: Decomposable Multiscale Mixing for Time Series Forecasting

来源论文iclr2024 论文地址&#xff1a;https://arxiv.org/abs/2405.14616 源码地址&#xff1a; https://github.com/kwuking/TimeMixer 背景 数据是有连续性&#xff0c;周期性&#xff0c;趋势性的。我们这篇文章主要围绕的是用MLP结构来预测数据的周期性具体为&#xff…

Springboot 使用EasyExcel导出含图片并设置样式的Excel文件

Springboot 使用EasyExcel导出含图片并设置样式的Excel文件 Excel导出系列目录&#xff1a;★★★★尤其注意&#xff1a;引入依赖创建导出模板类逻辑处理controllerservice 导出效果总结 Excel导出系列目录&#xff1a; 【Springboot 使用EasyExcel导出Excel文件】 【Springb…

【论文分享】基于街景图像识别和深度学习的针对不同移动能力老年人的街道步行可达性研究——以南京成贤街社区为例

全球老龄化趋势加剧, 许多城市中老年人数量不断增加&#xff0c;而现有街道和社区基础设施往往未能满足其步行安全和便利需求。本次我们给大家带来一篇SCI论文的全文翻译&#xff0c;该论文通过探讨不同步行能力的老年人对城市步行环境的需求&#xff0c;提供了关于如何改善城市…

LM2 : A Simple Society of Language Models Solves Complex Reasoning

文章目录 题目摘要简介相关工作方法论实验结果结论局限性 题目 LM2&#xff1a;简单的语言模型社会解决复杂推理问题 论文地址&#xff1a;https://aclanthology.org/2024.emnlp-main.920/ 项目地址&#xff1a; https://github.com/LCS2-IIITD/Language_Model_Multiplex 摘要…

【因果分析方法】MATLAB计算Liang-Kleeman信息流

【因果分析方法】MATLAB计算Liang-Kleeman信息流 1 Liang-Kleeman信息流2 MATLAB代码2.1 函数代码2.2 案例参考Liang-Kleeman 信息流(Liang-Kleeman Information Flow)是由 Liang 和 Kleeman 提出的基于信息论的因果分析方法。该方法用于量化变量之间的因果关系,通过计算信息…

[含文档+PPT+源码等]精品基于springboot实现的原生Andriod手机使用管理软件

软件开发环境及开发工具&#xff1a; 数据库管理工具&#xff1a;phpstudy/Navicat或者phpstudy/sqlyog 开发工具&#xff1a;Android Studio 后台管理系统涉及技术&#xff1a; 后台使用框架&#xff1a;Springboot 前端使用技术&#xff1a;Vue,HTML5,CSS3、JavaScript等…

(三十三)队列(queue)

文章目录 1. 队列&#xff08;queue&#xff09;1.1 定义1.2 函数1.3 习题1.3.1 例题&#xff08;周末舞会&#xff09; 2. 双向队列&#xff08;deque&#xff09;2.1 定义2.2 函数2.3 题目2.3.1 例题&#xff08;打BOSS&#xff09; 1. 队列&#xff08;queue&#xff09; 队…

常用数据类型

1.数值类型 分为整型和浮点型 double(3,1)&#xff1b;长度是3&#xff0c;小数点后是1&#xff0c;比如99.5&#xff0c;10.0&#xff0c;20.8 这里的float和double与java中的类似&#xff0c;都是IEEE 754标准的浮点数&#xff0c;精度会丢失&#xff0c;存在一定误差&#…

Vue3 -- 集成sass【项目集成5】

集成sass&#xff1a; 看过博主的 配置styleLint工具应该已经安装过 sass sass-loader 了&#xff0c;所以我们只需要加上我们的 lang"scss"即可。 <style scoped lang"scss"></style>给项目添加全局样式文件&#xff1a; 在src文件夹下创建…

【云原生系列--Longhorn的部署】

Longhorn部署手册 1.部署longhorn longhorn架构图&#xff1a; 1.1部署环境要求 kubernetes版本要大于v1.21 每个节点都必须装open-iscsi &#xff0c;Longhorn依赖于 iscsiadm主机为 Kubernetes 提供持久卷。 apt-get install -y open-iscsiRWX 支持要求每个节点都安装 N…

Springboot集成ElasticSearch实现minio文件内容全文检索

一、docker安装Elasticsearch &#xff08;1&#xff09;springboot和Elasticsearch的版本对应关系如下&#xff0c;请看版本对应&#xff1a; 注意安装对应版本&#xff0c;否则可能会出现一些未知的错误。 &#xff08;2&#xff09;拉取镜像 docker pull elasticsearch:7…

Diff 算法的误判

起源&#xff1a; 设想一下&#xff0c;假如你桌面上的文件都没有文件名&#xff0c;取而代之的是&#xff0c;你使用通过文件的位置顺序即index来区分它们———第一个文件&#xff0c;第二个文件&#xff0c;以此类推。也许这种方式可行&#xff0c;可是一旦你删除了其中的一…

D69【 python 接口自动化学习】- python 基础之数据库

day69 Python 执行 SQL 语句 学习日期&#xff1a;20241115 学习目标&#xff1a; MySQL 数据库&#xfe63;- Python连接redis 学习笔记&#xff1a; redis数据库的用途 使用Python访问redis数据库 使用Python对redis数据库进行读写操作 总结 1. redis是一款高性能的键…

飞书文档只读限制复制

飞书文档只读限制复制 场景描述解决方式插件安装测试 场景描述 当使用飞书时&#xff0c;可能会存在无对方文档编辑/管理权限&#xff0c;对方只给自己开放只读权限的时候&#xff0c;此时如果文档较重要&#xff0c;需要本地保存一份&#xff0c;但是又无法复制文档或直接屏蔽…

[每周一更]-(第123期):模拟面试|消息队列面试思路解析

文章目录 22|消息队列:消息队列可以用来解决什么问题?1. 你用过消息队列吗?主要用来解决什么问题?异步、削峰和解耦你能各举一个例子吗?2. 你用的是哪个消息队列?为什么使用它而不用别的消息队列?3. 为什么你一定要用消息队列?不用行不行?不用有什么缺点?4. 在对接多…

npm list @types/node 命令用于列出当前项目中 @types/node 包及其依赖关系

文章目录 作用示例常用选项示例命令注意事项 1、实战举例**解决方法**1. **锁定唯一的 types/node 版本**2. **清理依赖并重新安装**3. **设置 tsconfig.json 的 types**4. **验证 Promise 类型支持** **总结** npm list types/node 命令用于列出当前项目中 types/node 包及其…

使用 DBSCAN(基于密度的聚类算法) 对二维数据进行聚类分析

代码功能 生成数据&#xff1a; 使用 make_moons 方法生成一个非线性分布的二维数据集&#xff0c;模拟月亮形状的两个半环形分布&#xff0c;同时添加一定的噪声。 数据标准化&#xff1a; 使用 StandardScaler 对数据进行标准化处理&#xff0c;使不同特征的值具有相同的…

【苍穹外卖】学习日志-day1

目录 nginx 反向代理介绍 nginx 的优势 提高访问速度 负载均衡 保证后端服务安全 高并发静态资源 Swagger 生成 API 文档 Swagger 的使用方式 导入knife4j的maven坐标 在配置类中加入knife4j相关配置 设置静态资源映射 通过注解控制生成的接口文档 项目技术点 Token 模式 MD5 加…

炼码LintCode--数据库题库(级别:入门;数量:144道)--刷题笔记_01

目录 炼码LintCode数据库入门级别的笔记未完待续~~~ 炼码LintCode 数据库 入门级别的笔记 笔记如下&#xff0c;把所有涉及到的入门级别的知识点简单总结了一下。 以及一点点举一反三的写法。 增 INSERT INTO 表名 (列1, 列2, ...) VALUES (值1, 值2, ...);批量增 INSERT INT…

【C语言】连接陷阱探秘(1):声明与定义

目录 一、声明与定义的混淆 1.1. 声明(Declaration) 1.2. 定义(Definition) 1.3. 避免混淆的方法 1.4. 示例 二、声明与定义不匹配 2.1. 常见的不匹配情况 2.2. 解决方法 三、外部变量与静态变量的命名冲突 3.1. 外部变量命名冲突 3.2. 静态变量命名冲突 四、缺…