B2119 删除单词后缀

B2119 删除单词后缀

#include <iostream>

using namespace std;

# include <string.h>

#include <ctype.h>

#include <algorithm>

#include <string.h>

int main(){

  string word;

  cin>>word;

  if(word.size()> 2 && word.substr(word.size() - 2) == "er"){

    word = word.substr(0,word.size() - 2);

  }

  else if(word.size() > 2 && word.substr(word.size() - 2 ) == "ly"){

    word = word.substr(0,word.size() - 2);

  }

  else if(word.size() > 3 && word.substr(word.size() - 3 ) == "ing") {

    word= word.substr(0,word.size() - 3);

  }

  cout<<word;

}

/*### `strcmp(word + len - 2, "er")` 的解释

`strcmp` 是一个 C 标准库函数,用于**比较两个 C 风格的字符串**(即 `char` 数组)。它逐个字符比较两个字符串的 ASCII 值,直到遇到不同的字符或遇到字符串的终止符 `\0`。它的典型使用形式是 `strcmp(str1, str2)`,其返回值如下:

- 如果 `str1` 等于 `str2`,返回 `0`。

- 如果 `str1` 小于 `str2`(按字典顺序),返回负值。

- 如果 `str1` 大于 `str2`(按字典顺序),返回正值。

### `strcmp(word + len - 2, "er")` 的具体含义

- `word + len - 2` 是一个指针运算,表示从字符串 `word` 的倒数第二个字符开始。换句话说,它将 `word` 的内存地址偏移到 `len - 2` 的位置。

  - 例如,如果 `word` 是 `runner`,且 `len` 为 `6`,`word + len - 2` 就指向 `e`,因此相当于指向字符串 `"er"` 的起始位置。

- `strcmp(word + len - 2, "er")` 的作用是:

  - 比较从 `word` 的倒数第二个字符开始的子字符串与 `"er"` 是否相等。

  - 如果 `word` 以 `"er"` 结尾,`strcmp` 将返回 `0`,表示两者相等。

  - 如果 `word` 不是以 `"er"` 结尾,`strcmp` 会返回非零值。

### 使用这种方法的原因

- 由于 `strcmp` 比较的是两个完整的字符串,所以我们通过将指针移动到 `word` 的末尾以只比较后缀部分。

- 这样可以高效地判断一个字符串是否以某个特定的后缀结尾,而无需手动创建新的字符串或使用复杂的循环。

### 示例说明

假设有以下代码:

```c

char word[] = "runner";

int len = strlen(word);

if (strcmp(word + len - 2, "er") == 0) {

    printf("The word ends with 'er'.\n");

} else {

    printf("The word does not end with 'er'.\n");

}

```

- `len` 是 `6`,`word + len - 2` 指向字符串 `"er"` 的起始位置。

- `strcmp(word + len - 2, "er")` 比较的是字符串 `"er"` 与 `"er"`,结果返回 `0`,说明 `word` 确实以 `"er"` 结尾。

### 总结

- `strcmp` 的这种用法利用了指针偏移,直接从字符串的末尾位置开始比较。

- 这是在 C 语言中判断字符串后缀的一种有效方法,因为它避免了额外的字符串分配和拷贝。 */

你可以使用一个 `for` 循环来遍历 `patterbs` 数组,从而判断一个单词是否以指定的后缀(如 `er`、`ly`、`ing`)结尾。这个方法更加灵活和简洁,避免了多次 `if-else` 判断。以下是具体的实现方法:

### 示例代码

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

int main() {
    char word[33]; // 假设输入单词最大长度为 32
    cin >> word;

    // 定义后缀数组
    char patterns[][4] = {"er", "ly", "ing"};
    int len = strlen(word);

    // 遍历后缀数组进行匹配
    for (int i = 0; i < 3; ++i) {
        int patternLen = strlen(patterns[i]);
        if (len > patternLen && strcmp(word + len - patternLen, patterns[i]) == 0) {
            // 删除后缀
            word[len - patternLen] = '\0';
            break; // 退出循环,避免多次删除
        }
    }

    cout << word << endl;

    return 0;
}
```

### 解释

1. **定义后缀数组**:`char patterns[][4] = {"er", "ly", "ing"};`
   - `patterns` 是一个二维字符数组,存储需要检查的后缀。每个字符串的长度最多为 `3`,包括空字符 `\0`。

2. **遍历后缀数组**:
   - 使用 `for (int i = 0; i < 3; ++i)` 遍历所有后缀。
   - `strlen(patterns[i])` 获取当前后缀的长度 `patternLen`。

3. **检查并删除后缀**:
   - `if (len > patternLen && strcmp(word + len - patternLen, patterns[i]) == 0)` 检查 `word` 是否以当前后缀结尾。
     - `len > patternLen` 确保单词长度大于当前后缀长度,避免越界访问。
     - `strcmp(word + len - patternLen, patterns[i]) == 0` 用于比较单词的最后 `patternLen` 个字符和 `patterns[i]`。
   - 如果匹配成功,将单词的末尾截断,即 `word[len - patternLen] = '\0';`,从而删除后缀。
   - `break` 语句用于防止多次匹配和删除后缀。

### 代码优势

- **简洁性**:通过一个 `for` 循环和 `patterns` 数组,避免了多次 `if-else` 语句,代码更易于扩展和维护。
- **灵活性**:可以轻松扩展新的后缀,只需要在 `patterns` 数组中添加新元素。
- **效率**:使用 `strcmp` 和指针偏移操作实现快速判断和截断。

在你的示例中,`char patterns[][4] = {"er", "ly", "ing"};` 定义了一个 **二维字符数组**,用于存储需要检查的后缀字符串。让我详细解释这个定义的原理和细节。

### 二维字符数组的定义

1. **`char patterns[][4]` 的含义**:
   - 这是一个二维字符数组,其中每一行(即每个元素)都是一个**字符串**。
   - `4` 表示每个字符串最多可以包含 `3` 个有效字符加上一个**空字符 `\0`**(用于表示字符串结束)。因此,每个字符串的总长度是 `4` 字节。

2. **为什么使用 `4`**:
   - 这是因为最长的字符串是 `"ing"`,包含 `3` 个字符,加上末尾的空字符 `\0`,需要 `4` 个字节的空间。
   - 如果定义为 `char patterns[][3]`,就无法存储 `"ing"`,因为它需要额外的一个字节来存储 `\0` 终止符。

### 如何存储字符串

- `patterns` 是一个二维数组,每个元素实际上是一个 `char` 数组,也可以被视为一个字符串。
- 在内存中,`patterns` 的布局如下:

  ```
  patterns[0] = "er\0"
  patterns[1] = "ly\0"
  patterns[2] = "ing\0"
  ```

  每个字符串末尾都有一个 `\0` 作为字符串结束标志。

### 存储和访问方式

- **存储**:
  - `char patterns[][4]` 创建了一个包含 `3` 行、`4` 列的二维数组,总共占用 `3 x 4 = 12` 个字节的内存。
  - 每行是一个独立的 `char` 数组(字符串),所有行共享一个连续的内存空间。
  - 例如,`patterns[0]` 是一个指向 `"er"` 的 `char` 数组,`patterns[1]` 指向 `"ly"`,`patterns[2]` 指向 `"ing"`。
- **访问**:
  - `patterns[i]` 是一个指针,指向 `patterns` 中的第 `i` 行,即 `patterns[i]` 本身是一个 `char*`,表示一个字符串。
  - 可以通过 `strcmp(patterns[i], "er")` 或 `strlen(patterns[i])` 等字符串函数来操作这些字符串,就像处理普通的 `char*` 一样。

### 二维字符数组与一维字符串数组的区别

- **一维字符数组**:用于存储单个字符串。例如,`char word[33]` 可以存储一个最多为 `32` 个字符的字符串(包含终止符)。
- **二维字符数组**:用于存储多个字符串,每个字符串都有自己的长度和终止符。例如,`char patterns[][4]` 可以存储多个最长为 `3` 个字符的字符串,每个字符串末尾有 `\0`。

### 示例总结

```cpp
char patterns[][4] = {"er", "ly", "ing"};
```

- 这是一个二维字符数组,存储了三个字符串 `"er"`、`"ly"` 和 `"ing"`,每个字符串最多有 `3` 个字符加 `1` 个空字符。
- 你可以通过 `patterns[i]` 访问每个字符串,并使用标准的字符串操作函数(如 `strcmp`、`strlen`)对其进行操作。

是的,你理解得很对。`char patterns[][4] = {"er", "ly", "ing"};` 这种写法是允许的,因为编译器可以**自动推断出数组的行数**。这是 C 和 C++ 中二维数组定义的一种灵活性表现。

### 为什么可以省略行数 `3`

- **推断数组的大小**:当你定义 `char patterns[][4]`,并在初始化时提供了 `{"er", "ly", "ing"}` 三个元素,编译器会自动根据初始化列表的元素数量推断出行数为 `3`。
- **强制指定列大小**:列数 `4` 必须显式指定,因为在内存布局中,每行的大小是固定的,编译器需要知道每行能够存储多少个字符。
  - 每个字符串最多为 `3` 个字符,加上字符串结束符 `\0`,总共需要 `4` 个字符的空间。因此,我们必须指定 `4`。
  - 如果省略列数 `4`(即写成 `char patterns[][] = {"er", "ly", "ing"}`),编译器会报错,因为它无法推断出每行的大小。

### 如何解释 `char patterns[3][4]`

如果我们显式地写成 `char patterns[3][4] = {"er", "ly", "ing"};`,这表示一个二维字符数组,包含 `3` 行、`4` 列。每行都是一个 `char[4]` 数组,可以存储一个字符串,最多 `3` 个字符加 `1` 个空字符 `\0`。

### 编译器如何推断

- 在 `char patterns[][4] = {"er", "ly", "ing"};` 中,编译器根据提供的初始化列表 `{ "er", "ly", "ing" }` 看到有 `3` 个字符串,所以推断出数组有 `3` 行。
- 这就等效于写成 `char patterns[3][4] = {"er", "ly", "ing"};`。

### 省略行数的好处

- **简洁性**:在初始化时,如果你知道要存储的字符串数量,省略行数可以让代码更简洁。
- **灵活性**:如果以后修改了初始化列表的大小,编译器会自动调整行数,而不需要手动更改数组声明中的行数。

### 例子总结

```cpp
char patterns[][4] = {"er", "ly", "ing"};
```

- 编译器推断出有 `3` 行。
- 每行有 `4` 列,存储 `3` 个字符和一个终止符 `\0`。
- 等效于 `char patterns[3][4] = {"er", "ly", "ing"};`,但使用省略行数的写法更为简洁。

在这个例子中:

- 当 `word.size()` 是 `6` 时,`word.size() - 2` 计算出的是 `4`。
- `word.substr(word.size() - 2)` 从索引 `4` 开始,提取 `2` 个字符。这确实会包含从索引 `4` 开始的字符和索引 `5` 的字符(即最后两个字符)。

### 说明

- **索引从 `0` 开始**:字符串的索引是从 `0` 开始的,因此 `word.size() - 2` 指的是字符串倒数第二个字符的索引。
- **`substr()` 函数的行为**:`word.substr(start)` 生成从 `start` 索引开始的子字符串,直到字符串的末尾。`word.substr(start, length)` 则生成从 `start` 开始、长度为 `length` 的子字符串。

### 举例

假设 `word = "runner"`:

- `word.size()` 是 `6`。
- `word.size() - 2` 是 `4`,这对应于字符 `'e'` 的索引位置。
- `word.substr(4)` 或 `word.substr(4, 2)` 会提取从索引 `4` 开始的 `2` 个字符,即字符串 `"er"`。

### 总结

- **包含了第 `4` 个字符和第 `5` 个字符**:`word.substr(4, 2)` 包括索引 `4` 和 `5` 的字符,即字符串 `"er"`。
- 因为索引是从 `0` 开始,所以 `word.size() - 2` 确实表示倒数第二个字符的起始位置。

在这个示例中,我们使用了 `strcmp(word + len - patternLen, patterns[i])` 语句,它的作用是比较两个字符串:`word + len - patternLen` 和 `patterns[i]`。这是一个比较字符串尾部子字符串和给定模式的标准方式。让我详细解释其中的原理和工作机制:

### 1. **`strcmp` 的基本原理**

- `strcmp` 是一个来自 C 标准库 `<cstring>` 的函数,用于比较两个 C 风格的字符串。
- 它逐字符比较两个字符串的 ASCII 值,直到遇到不同的字符或遇到字符串结束符 `\0`。
- 返回值:
  - 如果两个字符串相等,`strcmp` 返回 `0`。
  - 如果第一个字符串小于第二个字符串(按字典顺序),返回负值。
  - 如果第一个字符串大于第二个字符串,返回正值。

### 2. **`strcmp(word + len - patternLen, patterns[i])` 的含义**

- `word + len - patternLen` 是一个指针运算,表示指向字符串 `word` 的某个位置。
  - `word` 是一个字符数组或指针,`len` 是 `word` 的总长度,`patternLen` 是我们要匹配的模式的长度(例如 `2` 或 `3`)。
  - `word + len - patternLen` 让指针从字符串末尾向前移动 `patternLen` 个字符,指向可能的后缀开始位置。
  - 例如,如果 `word = "running"`,`len = 7`,`patternLen = 3`,那么 `word + len - patternLen` 指向字符串 `"ing"` 的起始位置。

- `patterns[i]` 是我们要比较的模式字符串,如 `"er"`、`"ly"`、`"ing"` 等。

- `strcmp(word + len - patternLen, patterns[i])` 通过 `strcmp` 函数从指针位置开始比较 `word` 字符串的尾部和 `patterns[i]`。

### 3. **工作机制**

- 当 `strcmp(word + len - patternLen, patterns[i])` 被调用时,`strcmp` 会从 `word + len - patternLen` 指针开始,与 `patterns[i]` 逐字符进行比较。
  - 如果两者完全相等(包括长度和内容),`strcmp` 返回 `0`,表示匹配成功。
  - 如果不同,则返回一个非零值。

### 4. **示例操作**

假设 `word = "running"`,我们想判断它是否以 `"ing"` 结尾:

1. 计算长度:
   - `len = 7`(长度为 `7`,`r-u-n-n-i-n-g`)。
   - `patternLen = 3`(`"ing"` 的长度)。

2. 计算比较位置:
   - `word + len - patternLen = word + 7 - 3 = word + 4`。
   - 这意味着从 `word[4]` 开始,子字符串是 `"ing"`。

3. 比较:
   - `strcmp(word + 4, "ing")` 会比较 `word[4]` 到 `word[6]` 的内容与 `"ing"` 是否匹配。
   - 如果匹配,返回 `0`,否则返回非零值。

### 5. **为什么使用这种方式?**

- 这种方式利用了指针运算的强大功能,可以高效地从字符串的任意位置开始比较,而不需要额外的字符串复制或创建新字符串。
- 通过计算字符串长度和模式长度,我们可以灵活地检查字符串是否以特定后缀结尾,而不需要手动构建和遍历每个字符。

### 总结

- `strcmp(word + len - patternLen, patterns[i])` 的作用是从 `word` 字符串的尾部开始,与 `patterns[i]` 进行逐字符比较。
- 这种方式依赖于指针运算和 `strcmp` 的逐字符比较功能,能够高效判断字符串的尾部是否匹配特定模式。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AlohaKit:一组.NET MAUI绘制的开源控件

前言 今天大姚给大家分享一组.NET MAUI绘制的开源、免费&#xff08;MIT License&#xff09;UI控件库&#xff1a;AlohaKit。 MAUI介绍 .NET MAUI是一个开源、免费&#xff08;MIT License&#xff09;的跨平台框架&#xff08;支持Android、iOS、macOS 和 Windows多平台运…

漫谈分布式唯一ID

文章目录 本系列前言UUIDDB自增主键Redis incr命令号段模式雪花算法 本系列 漫谈分布式唯一ID&#xff08;本文&#xff09;分布式唯一ID生成&#xff08;二&#xff09;&#xff1a;leaf分布式唯一ID生成&#xff08;三&#xff09;&#xff1a;uid-generator分布式唯一ID生成…

C语言:文件操作2(又一万字?)

关于文件操作这章内容&#xff0c;因为知道内容较多所以我分两篇发了&#xff0c;但是还是没料到第二篇还是这么多&#xff0c;达到了一万多字&#xff01;&#xff01;&#xff01;作者本人真的将知识点进行了超级详解分析并且举了很多例子来帮助读者理解&#xff0c;本文章较…

STM32标准库-待机模式

1.1 STM32待机模式简介 STM32单片机具有低功耗模式&#xff0c;包括睡眠、停止和待机三种。 运行状态下&#xff0c;HCLK为CPU提供时钟。HCLK由AHB预分频器分频后直接输出得到。 低功耗模式选择需考虑电源消耗、启动时间和唤醒源。 睡眠模式停CPU不停外设时钟&#xff1b; 停止…

C++内存分区

内存分区 C程序在执行时&#xff0c;将内存大方向划分为4个区域 代码区&#xff1a;存放函数体的二进制代码&#xff0c;由操作系统进行管理的 全局区&#xff1a;存放全局变量和静态变量以及常量&#xff08;不包括局部常量&#xff09; 栈区&#xff1a;由编译器自动分配释…

大数据面试题--kafka夺命连环问

1、kafka消息发送的流程&#xff1f; 在消息发送过程中涉及到两个线程&#xff1a;一个是 main 线程和一个 sender 线程。在 main 线程中创建了一个双端队列 RecordAccumulator。main 线程将消息发送给双端队列&#xff0c;sender 线程不断从双端队列 RecordAccumulator 中拉取…

ElasticSearch备考 -- 集群配置常见问题

一、集群开启xpack安全配置后无法启动 在配置文件中增加 xpack.security.enabled: true 后无法启动&#xff0c;日志中提示如下 Transport SSL must be enabled if security is enabled. Please set [xpack.security.transport.ssl.enabled] to [true] or disable security b…

LeetCode:485.最大连续1的个数——简单题简单做

目录 题目——485.最大连续1的个数 题目分析&#xff1a; 图解如下&#xff1a; 代码如下 题目——485.最大连续1的个数 给定一个二进制数组 nums &#xff0c; 计算其中最大连续 1 的个数。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,0,1,1,1] 输出&#xff1a;3 解…

如何在Android中自定义property

在Android中创建自定义的属性&#xff08;Android property&#xff09;通常用于调试、性能调优或传递应用和系统之间的信息。 以下是如何在Android中创建和使用自定义属性的步骤&#xff1a; 1. 定义属性 在Android中&#xff0c;属性是以“属性名称属性值”形式定义的键值对…

web——sqliabs靶场——第二关

今天来搞第二关&#xff0c;来看看是什么咸蛋 1.判断是否存在sql注入漏洞 输入1 存在sql注入&#xff0c;报错语句为 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near LIMIT 0,1 …

时序预测 | Python基于CNN-transformer时间序列预测

时序预测 | Python基于CNN-transformer时间序列预测 目录 时序预测 | Python基于CNN-transformer时间序列预测预测效果基本介绍参考资料 预测效果 基本介绍 时序预测 | Python基于CNN-transformer时间序列预测 Cnn-transformer-自适应稀疏自注意力ASSA-对比归一化contranorm预…

windows中docker安装redis和redisinsight记录

创建一个Redis运行容器&#xff0c;命令如下 docker run -it -d --name redis -p 6379:6379 redis --bind 0.0.0.0 --protected-mode no -d 代表Redis容器后台运行 --name redis 给创建好的容器起名叫redis -p 6379:6379 将容器的6379端口映射到宿主机的6379端口&#xff0c;注…

ClickHouse创建账号和连接测试

在之前搭建ClickHouse的时候&#xff0c;把账户相关的去掉了&#xff0c;所以登录和连接的时候是不需要账号密码的&#xff0c;但是实际项目中&#xff0c;肯定是需要根据需要创建账号。 一&#xff0c;创建账号 1&#xff0c;进入到 /etc/clickhouse-server&#xff0c; 编辑…

基于微信小程序实现个人健康管理系统

作者主页&#xff1a;编程千纸鹤 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验&#xff0c;被多个学校常年聘为校外企业导师&#xff0c;指导学生毕业设计并参…

基于python的天气数据采集与可视化分析,对20个城市的天气适宜出行度分析

摘要 本项目旨在基于Python对20个城市的天气数据进行采集与可视化分析&#xff0c;以评估天气的适宜出行度。该分析通过四个主要指标进行量化&#xff0c;这些指标分别是天气状况良好率、空气质量优良率、气温适宜率和安全天气率。通过这些指标&#xff0c;我们能够有效地判断…

YOLOv11实战宠物狗分类

本文采用YOLOv11作为核心算法框架&#xff0c;结合PyQt5构建用户界面&#xff0c;使用Python3进行开发。YOLOv11以其高效的特征提取能力&#xff0c;在多个图像分类任务中展现出卓越性能。本研究针对5种宠物狗数据集进行训练和优化&#xff0c;该数据集包含丰富的宠物狗图像样本…

电信网关配置管理系统 upload_channels.php 文件上传致RCE漏洞复现

0x01 产品简介 中国电信集团有限公司(英文名称“China Telecom”、简称“中国电信”)成立于2000年9月,是中国特大型国有通信企业、上海世博会全球合作伙伴。电信网关配置管理系统是一个用于管理和配置电信网络中网关设备的软件系统。它可以帮助网络管理员实现对网关设备的远…

Halcon LED灯带检测分享

目录 原图 检出图 示例代码 函数说明 代码 原图 检出图 示例代码 函数说明 LEDSensitivity : 0.6 LEDMinSize : 35 LEDMaxSize : 400 LEDMethod : 1 LEDType :1 LED (Image, LEDDefectTrans, LEDSensitivity, LEDMethod, LEDType, LEDMinSize, LEDMaxSize, R, G, B,…

Pytest-Bdd-Playwright 系列教程(7):使用测试代码生成辅助工具

Pytest-Bdd-Playwright 系列教程&#xff08;7&#xff09;&#xff1a;测试代码生成辅助工具的使用 前言一、代码生成辅助工具的设计思路1.1 功能概览1.2 适用人群 二、如何使用 pytest-bdd 代码生成器三、代码生成器的实际应用场景3.1 初学者的学习和实践3.2 大规模功能测试3…

【每日刷题】Day152

【每日刷题】Day152 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;每日刷题&#x1f34d; &#x1f33c;文章目录&#x1f33c; 1. LCR 176. 判断是否为平衡二叉树 - 力扣&#xff08;LeetCode&#xff09; 2. 最大子矩阵_牛客题霸…