Text Reverse

OJ: HDU

题目 ID: 1062

标签:

日期: 2025-12-31 12:11

这是一道非常经典的利用栈(Stack)“后进先出”(LIFO, Last In First Out)特性来解决字符串处理的题目。

这个问题(通常对应 HDU OJ 1062 Text Reverse)的核心在于:单词内部的字符需要反转,但单词与单词之间的顺序不变。

核心思路

栈的特性是“先进后出”,这正好对应“反转”的操作。

  1. 遍历字符串:从左到右逐个读取字符。
  2. 遇到普通字符:如果是单词的一部分,将其压入栈(Push)
  3. 遇到空格:说明前一个单词结束了。此时栈里保存的是该单词的所有字符(顺序是反的)。我们依次**弹出栈(Pop)**并打印字符,就能得到正序的单词。然后,直接原样输出这个空格。
  4. 遇到换行符/字符串结束:说明整行结束。将栈中剩余的字符全部弹出并打印(处理这一行最后一个单词),然后输出换行符。

图解流程

以输入 olleh !dlrow 为例:

  1. 读取 ‘o’, ‘l’, ‘l’, ‘e’, ‘h’: 依次入栈。
  • 此时栈(从底到顶): [o, l, l, e, h]
  1. 读取 ’ ’ (空格): 触发输出。
  • 循环弹栈输出: h -> e -> l -> l -> o (输出了 “hello”)
  • 输出空格本身。
  • 此时屏幕显示: hello ,栈为空。
  1. 读取 ‘!’, ‘d’, ‘l’, ‘r’, ‘o’, ‘w’: 依次入栈。
  • 此时栈(从底到顶): [!, d, l, r, o, w]
  1. 读取结束: 触发输出。
  • 循环弹栈输出: w -> o -> r -> l -> d -> ! (输出了 “world!”)
  • 此时屏幕显示: hello world!

C++ 代码实现

这里使用 C++ 标准库中的 <stack>getline(比 gets 更安全且现代,但逻辑是一样的)。

cpp
#include <iostream>
#include <stack>
#include <string>
#include <cstdio> // 用于 getchar

using namespace std;

int main() {
    int t;
    // 读取测试用例数量
    cin >> t;
    
    // 【关键点1】吃掉输入整数T后的换行符
    // 如果不写这一句,后面的 getline 会直接读到一个空行
    getchar(); 

    while (t--) {
        string line;
        // 读取整行包含空格的文本
        getline(cin, line);
        
        stack<char> s;
        
        // 遍历这一行的每一个字符
        for (int i = 0; i < line.length(); i++) {
            if (line[i] == ' ') {
                // 【关键点2】遇到空格,说明一个单词结束
                // 将栈中所有字符弹出并打印
                while (!s.empty()) {
                    cout << s.top();
                    s.pop();
                }
                // 打印空格本身
                cout << " ";
            } else {
                // 普通字符,压入栈中
                s.push(line[i]);
            }
        }
        
        // 【关键点3】处理最后一个单词
        // 循环结束后,栈里可能还有最后一个单词的字符(因为行尾可能没有空格)
        while (!s.empty()) {
            cout << s.top();
            s.pop();
        }
        
        // 每个测试用例输出后换行
        cout << endl;
    }
    
    return 0;
}

题目解析与注意事项

1. 为什么需要 getchar()

当你使用 cin >> t; 输入数字(例如 3)并按下回车键时,输入缓冲区里实际是 3\ncin 读取了 3,但 \n(换行符)还留在缓冲区里。 如果不加 getchar(),随后的 getline(或 gets)会认为遇到了换行符,直接读取一个空字符串,导致第一个测试用例输出错误。

2. 关于 gets()getline()

题目提示中提到的 gets() 是 C 语言的老函数,因为存在严重的缓冲区溢出安全隐患,在现代 C++(C++14 及以后)中已经被移除。

  • 推荐做法:使用 C++ 的 getline(cin, string_variable)
  • 如果不使用 String 类:可以使用 cin.getline(char_array, size)fgets

3. 边界处理

最容易犯错的地方是行尾的那个单词。 循环逻辑是“遇到空格才输出栈内容”。如果一行文本的末尾没有空格(通常都是这样),循环结束后,最后一个单词还在栈里。所以必须在循环外面再写一次 while (!s.empty()) 的输出逻辑。