博客
关于我
【PTA】 敲笨钟 (20 分)
阅读量:529 次
发布时间:2019-03-09

本文共 3180 字,大约阅读时间需要 10 分钟。

如何解决字符串替换问题?今天我们要解决一个很有趣的编程问题。这个问题看起来简单,但到了实际应用,却发现其中的陷阱。让我带你一步一步地分析这个过程。

问题描述是这样的:假设我们有一个由字符'a''b'交替组成的字符串。我们需要找到这个字符串中最后一次出现"ong"的位置,并将其替换为"bng"。听起来并不复杂,但如果直接用简单的方法尝试,可能会遇到很多麻烦。这个问题考查的是字符串操作的应用,是许多开发者在日常工作中可能会遇到的。

我的思路:逐字符替换

一开始,我想直接使用字符串的**replace**方法。毕竟,replace函数是用来处理字符串替换的嘛。那我就想着把"ong"替换成"bng"。但问题很快就暴露了:replace方法会将所有匹配的子串都替换掉。所以,当我试图只替换最后一个出现"ong"时,结果并不是预期的。

更具体地说,当我使用string.find()replace()的时候,所有"ong"都会被替换,而不是仅替换最后一次出现的。比如说,如果字符串是"abonnglepongu",原始的replace方法会把它变成"abonbgbngugu"(结果可能不是这样,但肯定不是我们想要的结果)。所以,我意识到自己最初的方法有问题。

教师的思路:直接从后往前寻找位置

老师给的简洁版代码更让我感触深刻。他完全不用replace函数,而是直接从后往前寻找"ong"的位置,然后手动修改输出。这看起来虽然繁琐,但却非常高效。因为字符串的长度有限(比如100个字符),这种方法完全可行。

具体来说,老师采用的方法是:

  • 从字符串的最后一个字符开始向前查找"o"
  • 一旦找到了"o",然后检查它后面是否有两个"n"和一个"g"
  • 如果满足条件,就标记这个位置。
  • 最后,将这个"ong"替换成"bng",并输出完整的字符串。
  • 这种方法虽然看起来有点笨,但非常可靠,因为它不会遗漏任何最后出现的"ong"

    AC代码1:我的初步尝试

    接下来,让我来展示一下我的初步代码。这个代码虽然解决了问题,但后来因为错误的范围设置而被老师批评:

    #include 
    #include
    using namespace std;int main() { int n; cin >> n; while (n--) { string a; cout << "请输入第" << n << "个字符串:\n"; getline(cin, a); int temp1 = a.find(',', 0); // <----- 这里有误,导致find函数返回-1 // 由于我错误地使用了find函数的参数 // 后续代码会因为temp1的错误而出问题 }}

    AC代码2:老师的简洁版

    老师的代码简洁而有效。完整的代码如下:

    #include 
    #include
    #include
    using namespace std;int main() { char s[101]; int n; cin >> n; int i, j, k; for (i = 0; i < n; ++i) { cout << "请输入第" << (i + 1) << "个字符串:\n"; fgets(s, sizeof(s), stdin); // 寻找最后一个"ong"的位置 j = s.length() - 1; k = -1; while (j >= 4 && k == -1) { if (s[j] == 'o' && s[j-1] == 'n' && s[j-2] == 'g') { k = j; } --j; } if (k != -1) { // 替换成"bng" s[k] = 'b'; s[k-1] = 'n'; s[k-2] = 'g'; cout << "修改后的字符串:" << s << endl; } else { cout << "未发现ong" << endl; } }}

    两种方法对比

    从代码中可以看到,我的初态确实有问题,特别是find函数的参数设置错误。此外,replace函数的使用也暴露了一个陷阱:它会替换所有的匹配项,而不是仅替换最后一个。

    而老师的方法更为注重细节。他不使用replace函数,而是通过反向遍历字符串,找到最后出现的"ong",然后直接修改字符。这对于字符串长度不太大的情况,效率并不是特别重要,但逻辑清晰,避免了潜在的错误。

    可能的优化思路

    其实,还有另一种更优化的方法,就是利用find函数返回的位置值,将其作为范围参数,使用replace函数替换特定的位置。这虽然和老师的方法有些相似,但代码可以更加简洁。具体代码如下:

    #include 
    #include
    using namespace std;int main() { int n; cin >> n; for (int i = 0; i < n; ++i) { string a, b; cout << "请输入第" << i + 1 << "个字符串:\n"; getline(cin, a); // 查找最后一个","的位置 size_t pos = a.find(',', 0); // 修正find的范围参数错误 if (pos != string::npos) { string prefix = a.substr(0, pos -= 3); // 假设字符串中存在从pos位置往前三位的"ong" string modified = a.replace(pos, 3, "bng"); // 输出修改后的字符串 cout << "修改后的字符串:" << modified << endl; } else { cout << "未发现字符"," << endl; } }}

    这种方法虽然保留了replace函数的使用,但修复了我之前的错误,特别是在find函数的范围参数设置上。这能够更可靠地找到最后出现的"ong",并仅替换它。

    最终总结

    快速总结一下本次的经验:

  • 不能盲目使用replace函数,要清楚它的作用和限制。
  • 有时候直接逆向思维,逐个字符查找和替换,能够解决问题。
  • 代码的每一行都要仔细检查,避免低级错误。
  • 在多次尝试后发现哪种方法更优,然后就可以写出最终的代码。
  • 希望这遍调研过程对你有所帮助!如果你有进一步的疑问,欢迎留言讨论。

    转载地址:http://hieiz.baihongyu.com/

    你可能感兴趣的文章
    VTK:可视化之Arbitrary3DCursor
    查看>>
    VTK:可视化之BackfaceCulling
    查看>>
    VTK:可视化之LoopShrink
    查看>>
    li 修改前面小圆点的颜色
    查看>>
    vue h5 真机调试
    查看>>
    Java 内存分配详解(六)
    查看>>
    在内存中java类和对象的区别
    查看>>
    虚拟机virtualbox设置界面最大化
    查看>>
    Java处理时间Date
    查看>>
    CentOS 7 修改ip、MAC、UUID
    查看>>
    go语言中select实现优先级
    查看>>
    web前端-CSS-字体属性
    查看>>
    web前端-CSS-媒体查询响应式和多列
    查看>>
    yolov2.cfg与yolov3配置文件参数解析
    查看>>
    【leetcode-字符串】外观数列
    查看>>
    【leetcode】Shuffle an Array 打乱一个没有重复元素的数组
    查看>>
    [notes] JSON notes
    查看>>
    [设计模式]策略模式(strategy)---算术运算
    查看>>
    设计模式之——桥接模式(Bridge)
    查看>>
    高性能MySQL——第三章服务器性能剖析
    查看>>