这道PTA天梯赛的Left-pad题目看似简单,但涉及了几个C++字符串处理的关键知识点。我们先来看题目要求:
题目要求我们实现一个类似Linux系统中left-pad命令的功能:给定一个字符串s、一个字符c和一个数字n,当字符串长度小于n时,在左侧用字符c填充至长度n;当字符串长度大于等于n时,只保留字符串最右侧的n个字符。
在实际编码中,第一个遇到的难题就是输入处理。很多初学者会直接这样写:
cpp复制cin >> n >> c;
getline(cin, s);
结果发现s总是空字符串。这是因为cin >> n >> c读取完数字和字符后,输入缓冲区中会残留一个换行符\n,而getline()会立即读取到这个换行符,导致s为空。
解决方案是使用cin.ignore()清除缓冲区中的换行符:
cpp复制cin >> n >> c;
cin.ignore(); // 清除缓冲区中的换行符
getline(cin, s);
注意:
cin.ignore()默认只忽略缓冲区中的第一个字符。如果需要忽略多个字符,可以指定参数,如cin.ignore(100, '\n')表示忽略最多100个字符,直到遇到换行符为止。
根据题目要求,我们需要处理两种情况:
对于第二种情况,C++的substr()函数可以完美解决:
cpp复制s.substr(start_idx, n)
其中start_idx = s.size() - n,表示从哪个位置开始截取。
下面我们来看完整的AC代码,并逐段解析:
cpp复制#include <iostream>
#include <string>
using namespace std;
int main() {
int n;
char c;
string s;
// 1. 读取数字和字符
cin >> n >> c;
// 忽略缓冲区中残留的换行符,避免getline读取空字符串
cin.ignore();
// 2. 读取完整的字符串(包含空格)
getline(cin, s);
int len = s.size();
if (len < n) {
// 字符串长度不足n:前面补c,补够n个字符
// 需要补的字符数 = n - len
int pad_num = n - len;
// 先输出补的字符
for (int i = 0; i < pad_num; ++i) {
cout << c;
}
// 再输出原字符串
cout << s << endl;
} else {
// 字符串长度超过/等于n:截取最后n个字符
// 正确的起始索引 = 总长度 - n
int start_idx = len - n;
// 从start_idx开始,截取n个字符
cout << s.substr(start_idx, n) << endl;
}
return 0;
}
输入处理部分:
cin.ignore()清除缓冲区中的换行符getline()读取完整字符串(包含空格)逻辑处理部分:
lenlen < n,计算需要填充的字符数pad_num = n - len,然后循环输出填充字符,最后输出原字符串len >= n,计算起始位置start_idx = len - n,使用substr()截取最后n个字符输出substr()是C++字符串处理中非常实用的函数,其原型为:
cpp复制string substr(size_t pos = 0, size_t len = npos) const;
pos:起始位置(从0开始计数)len:要截取的字符数(如果不指定,则截取到字符串末尾)注意:
pos不能超过字符串长度,否则会抛出out_of_range异常。在实际使用中,我们应该确保pos是合法的。
问题现象:getline()读取到的字符串总是空。
原因分析:
cin >>操作在缓冲区留下了换行符getline()立即读取到这个换行符,认为输入结束解决方案:
getline()前使用cin.ignore()清除缓冲区getline()读取所有输入,然后解析在编写这类字符串处理题目时,特别需要注意边界条件:
getline()正确读取虽然本题对性能要求不高,但我们可以思考如何优化:
substr()会创建新字符串,对于大字符串可能影响性能reserve()足够空间除了substr(),C++字符串处理还有以下常用函数:
find():查找子字符串replace():替换子字符串erase():删除部分字符insert():插入字符compare():字符串比较这种字符串填充操作在实际开发中很常见,例如:
在实际编程竞赛和开发中,我总结了以下几点经验:
cin和getline()时,缓冲区问题很常见substr()这样的函数可以大大简化代码对于这道题,最关键的收获是理解了cin.ignore()的用法和substr()函数的灵活应用。这些知识点在后续的字符串处理题目中会反复用到。