B2121 最长最短单词

B2121 最长最短单词

#include <iostream>
using namespace std;
# include <string.h>
#include <ctype.h>
#include <algorithm>
#include <string.h>
#include <vector>
int main(){
  char str[30000];
  cin.getline(str,30000);
  char delimiter[] = " ,.";
  auto token = strtok(str,delimiter);
  char shortest [101],longest [101];
  strcpy(shortest,token);//使用 strcpy 将第一个单词初始化为当前最短和最长单词
  strcpy(longest,token);//使用 strcpy 将第一个单词初始化为当前最短和最长单词
  while(token){
    if(strlen(token) < strlen(shortest)){
      strcpy(shortest,token);
    }
    if(strlen(token) > strlen(longest)){
      strcpy(longest,token);
    }
    token = strtok(NULL,delimiter);
  }
  cout<<longest<<endl;
  cout<<shortest<<endl;
}

在你的代码中,`strtok(NULL, delimiter)` 的第二次调用会继续分割字符串,这是因为 `strtok` 具有**内部状态机制**,它会记住上一次分割的位置。这是 `strtok` 的一个关键特性,使它能够在循环中逐步解析整个字符串。

### 详细解释

1. **第一次调用 `strtok(str, delimiter)`**:
   - 第一次调用 `strtok` 时,你传入的是字符串 `str` 和分隔符 `delimiter`。`strtok` 会找到字符串中的第一个分隔符,并将其替换为 `\0`,然后返回指向第一个子字符串的指针(即第一个 token)。
   - 内部状态指向分隔符后的第一个字符,为下一次调用做准备。

2. **后续调用 `strtok(NULL, delimiter)`**:
   - 在后续调用中,传递 `NULL` 作为第一个参数。`strtok` 会从上一次调用结束的位置继续搜索下一个分隔符。
   - 它会找到下一个分隔符并将其替换为 `\0`,然后返回下一个子字符串的指针。
   - `strtok` 会继续执行这个过程,直到没有更多的 token,返回 `NULL`。

### 为什么第二次调用会在这里

- `strtok(NULL, delimiter)` 的工作方式决定了它会继续从字符串上次分割的位置继续查找下一个 token。
- 它利用了内部的静态变量来记住分割的位置,所以传入 `NULL` 时,它知道继续处理上次的字符串。
- 这就是为什么在你的 `while` 循环中,`token = strtok(NULL, delimiter);` 能够不断地获取下一个 token,直到所有分隔符都被处理完毕并返回 `NULL`。

### 示例

考虑字符串 `"Hello, world. This is a test."` 和分隔符 `" ,."`:

1. **第一次调用**:`token = strtok(str, delimiter);`
   - 结果:返回 `"Hello"`,`strtok` 内部记住了分割位置,指向 `world`。

2. **第二次调用**:`token = strtok(NULL, delimiter);`
   - 结果:返回 `"world"`,`strtok` 继续记住分割位置,指向 `This`。

3. **接下来的调用**:
   - 每次 `strtok(NULL, delimiter)` 都会继续从上次分割的位置查找下一个 token,直到没有更多 token 返回 `NULL`。

### 总结

- `strtok(NULL, delimiter)` 的工作机制依赖于它记住上一次分割的位置,这样可以在一个循环中逐步解析整个字符串。
- 通过这种方式,你可以逐个获取分割的 token,直到字符串被完全解析。

`strcpy` 是一个 C/C++ 标准库函数,用于将一个字符串复制到另一个字符串中。它的定义在 `<cstring>` 头文件中。它的作用是**将源字符串的内容复制到目标字符串中**,包括字符串的终止符 `\0`。具体到你在代码中的使用,它的作用是**将第一个单词初始化为当前的最短和最长单词**。

### `strcpy` 的作用和用法

- 原型:`char* strcpy(char* destination, const char* source);`
  - `destination` 是目标字符串,即被复制到的地方。
  - `source` 是源字符串,即要复制的内容。
- `strcpy` 会将 `source` 的内容复制到 `destination`,并在 `destination` 末尾添加 `\0`,标记字符串结束。

### 在你的代码中使用

```cpp
strcpy(shortest, token);
strcpy(longest, token);
```

- 这两行代码的作用是将 `token`(第一个分割出来的单词)分别复制到 `shortest` 和 `longest` 中,作为初始值。
- 因为你需要在接下来的逻辑中找出第一个最长和第一个最短的单词,所以用 `strcpy` 复制初始的单词。这样,后续判断时有一个基准值可以比较。

### 为什么需要 `strcpy`?

- 在 C/C++ 中,字符串是用 `char` 数组存储的,直接赋值(如 `shortest = token;`)是不被允许的。
- `strcpy` 是将 `token` 的内容逐字符地复制到 `shortest` 和 `longest` 中。它确保 `shortest` 和 `longest` 存储了 `token` 的内容,并且是独立的存储,不会受后续对 `token` 的修改影响。

### 示例

假设 `token` 取值为 `"example"`:

```cpp
char shortest[101];
strcpy(shortest, token);
```

- `strcpy(shortest, token)` 会将 `"example"` 的内容复制到 `shortest`,包括末尾的 `\0`。
- 复制完成后,`shortest` 变为一个包含字符串 `"example"` 的 `char` 数组。

### 总结

- `strcpy` 用于将一个字符串复制到另一个字符数组中,适用于字符串的初始化和赋值操作。
- 在你的代码中,它用于初始化 `shortest` 和 `longest`,使它们可以在接下来的比较中被更新。

你的代码逻辑通过 `strtok` 函数将输入字符串按指定的分隔符(空格、逗号、句号)分割成单词,并在遍历过程中找到第一个最长和第一个最短的单词。让我详细解释代码的逻辑和各个部分的作用:

### 代码逻辑说明

1. **读取输入**

   ```cpp
   char str[30000];
   cin.getline(str, 30000);
   ```
   - `str` 是一个大小为 `30000` 的字符数组,用于存储输入的字符串。
   - `cin.getline(str, 30000);` 读取一行最多 `30000` 个字符的输入,包括空格和其他分隔符。

2. **定义分隔符**

   ```cpp
   char delimiter[] = " ,.";
   ```
   - `delimiter` 是一个字符数组,包含三个分隔符:空格 `' '`, 逗号 `','`,句号 `'.'`。
   - 这些分隔符用于分割输入字符串中的单词。

3. **使用 `strtok` 分割字符串**

   ```cpp
   auto token = strtok(str, delimiter);
   ```
   - `strtok` 是 C 语言中用于分割字符串的函数。它会将 `str` 按照 `delimiter` 中的任一字符进行分割,返回第一个子字符串(即单词)的指针。
   - 如果找到一个分隔符,它会将分隔符替换为 `\0`,并返回下一个子字符串的指针。
   - 第一次调用 `strtok` 需要传入要分割的字符串,后续调用则传入 `NULL`,表示继续在同一个字符串中寻找下一个分隔符。

4. **初始化最短和最长单词**

   ```cpp
   char shortest[101], longest[101];
   strcpy(shortest, token);
   strcpy(longest, token);
   ```
   - `shortest` 和 `longest` 数组用于存储当前找到的最短和最长单词,长度限制为 `100` 个字符加上终止符 `\0`。
   - 使用 `strcpy` 将第一个单词初始化为当前最短和最长单词。

5. **遍历剩余的单词**

   ```cpp
   while (token) {
       if (strlen(token) < strlen(shortest)) {
           strcpy(shortest, token);
       }
       if (strlen(token) > strlen(longest)) {
           strcpy(longest, token);
       }
       token = strtok(NULL, delimiter);
   }
   ```
   - 在循环中,每次调用 `strtok(NULL, delimiter)` 来获取下一个单词,直到没有更多的单词返回 `NULL`。
   - 对每个单词:
     - 如果当前单词的长度小于 `shortest`,就将 `shortest` 更新为当前单词。
     - 如果当前单词的长度大于 `longest`,就将 `longest` 更新为当前单词。
   - 通过 `strlen(token)` 获取当前单词的长度,并使用 `strcpy` 复制新的最短或最长单词。

6. **输出结果**

   ```cpp
   cout << longest << endl;
   cout << shortest << endl;
   ```
   - 最后,输出找到的第一个最长单词和第一个最短单词。

### 总结

- 你使用 `strtok` 将输入字符串按空格、逗号和句号分割成多个单词,并用 `shortest` 和 `longest` 保存第一个最短和最长的单词。
- `strtok` 在分割字符串时会破坏原始字符串(替换分隔符为 `\0`),但这是符合逻辑的,符合程序需求。
- 代码逻辑通过一次遍历和简单比较高效地找到了所需结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值