【问题标题】:Going from one instance of string.find to the next从 string.find 的一个实例转到下一个
【发布时间】:2020-11-22 22:15:17
【问题描述】:

嗯,这是另一个经典的谜题……我的目标是取出字符串中每个单词的第一个字母,并将其放在该单词的末尾加上 -ay(猪拉丁语)。我设法改变了第一个词。但是我该如何进入下一个呢?我咨询了不同的来源、论坛,但我仍然卡住了......有什么提示吗? :) 可能类似于:pos = a.find(" ", pos +1)?见以下代码:

#include <iostream>
#include <string>


int main()

{
    std::string a = "hello what is going on";
    std::string b = "ay ";
    std::size_t pos = a.find(" ");
    int length = a.length();
    std::string first = a.substr(0,1);

        for (int i = 0; i <= length; i++)
        {   
            if (pos != std::string::npos)
                {
                a.replace(pos, a.length(), first + b);   //I guess I have to change sth. here.
                }                                        //Maybe a while-loop?
        }

    a.replace(0, 1, "");
    std::cout << a;            //Output: "ellohay"; **goal**: "ellohay hatway siay oingay noay"
    
}

【问题讨论】:

  • 我会将字符串拆分为字符串向量,然后循环操作每个字符串
  • 嗯,你已经知道大部分答案了。当你尝试类似pos = a.find(" ", pos +1) 时发生了什么?
  • 另外,Pig Latin 也不是那么简单。
  • @Igor Tandetnik:出现了这样的事情:ellohayhayhayhayhayhayhayhayhayhayh。 :)
  • @Thomas Sablik:我会试试的。由于我还没有使用矢量,因此需要阅读有关如何执行此操作的内容。

标签: c++ string replace


【解决方案1】:

与字符串操作任务一样,非常保留单独的“源”和“目标”字符串,而不是尝试“即时”修改单个字符串。

对于您的情况,以下PigLatin 函数可以满足您的要求(尽管我不是在这里尝试验证您对 Pig Latin 的定义)。它还可以处理单词之间的多个空格,并有一个代码块来处理不是字母或空格的字符,您可以根据需要对其进行修改。

#include <iostream>
#include <string>

std::string PigLatin(std::string & input)
{
//  if (input.empty()) return ""; // Not sure what you want to do with empty strings?
    std::string answer = "";
    bool inword = false;
    char firstc = ' '; // Never used unitialized, but give it a value to silence the warning
    for (auto testc : input) {
        if (std::isspace(testc)) { // Space: check if we have a current word...
            if (inword) {          // ... and add last char + "ay" if we do
                answer += firstc;
                answer += "ay";
            }
            inword = false;        // Flag that we are now outside a word
            answer += testc;       // And add this space to the answer.
        }
        else if (std::isalpha(testc)) { // Letter: Check if it's the first in a word...
            if (!inword) firstc = testc; // If so, store it for future use
            else answer += testc;        // Otherwise append to the answer
            inword = true;
        }
        else { // Non-alpha, non-space ...
            answer += testc;
        }
    }
    // Handle terminal case, where we have a word without a space after it:
    if (inword) {
        answer += firstc;
        answer += "ay";
    }
    return answer;
}

int main()
{
    std::string a = "hello ... what is   going on";
    std::string b = PigLatin(a);
    std::cout << b << std::endl;
    return 0;
}

请随时要求进一步澄清和/或解释。

【讨论】:

  • 我喜欢这段代码,因为您使用“基本”技术(if、else 等)。我对编码还是很陌生(几个月前开始),所以我没有使用代码中的某些部分,例如 std::isspace 或 std::isalpha。谢谢你的想法!!
【解决方案2】:

很简单:

只需对字符串进行标记,获取每个标记,将标记的第一个字符保存在某个 var 中,删除第一个字符并构建您需要的内容。

#include <iostream>
#include <sstream>
#include <string>

using namespace std;

int main() {
  // build istringstream object from provided text
  auto input = istringstream{"hello what is going on"};

  string token = "";
  string output = "";

  // tokenize provided text input
  while(input >> token) {
    char first = token[0]; // save the first char of token
    token.erase(0, 1); // remove the first char from token
    output = output + token + first + "ay" + " "; // build what you need
  }

  // okay, print output to check if everything is okay
  cout << output << endl;
  
  return 0;
}

输出是:

ellohay hatway siay oinggay noay

[P.S.]:如果您对此代码/解决方案方法有任何疑问,请随时提问。

【讨论】:

    【解决方案3】:

    这是使用标准算法做你想做的事情的简单方法:

    std::ostringstream result;  // to store the result
    
    std::istringstream iss{a};  // convert string to stream
    
    std::transform(std::istream_iterator<std::string>{iss}, 
                   std::istream_iterator<std::string>{},    
                   std::ostream_iterator<std::string>{result},
                   [&b](auto const &word) {
                       return word.substr(1) + word[0] + b;   // pig latin
                   });
    
    std::cout << result.str();  // convert output stream to string             
    

    这是demo

    【讨论】:

    • 谢谢你!这似乎是最紧凑的解决方案 :) 现在我只需要弄清楚所有不同部分的实际作用......
    • @BisAndiGrenzen 看看transformistream_iterator。这应该会有所帮助。
    【解决方案4】:

    好的,多亏了你们所有人,我想出了某种“混合”实现你们的想法,就像这样:

    #include <iostream>
    #include <string>
    
    
    int main()
    
    {
        std::string a = "hello what is going on";
        std::string b = "ay ";
        std::string c = "ay";
        std::string delimiter = " ";
        std::size_t pos = 0;
        std::string token;
        std::string output = "";
        
    
        while ((pos = a.find(delimiter)) != std::string::npos)
        {
            token = a.substr(0, pos);
            char first = token[0];
            token.replace(pos, token.length(), first + b);
            token.erase(0, 1);
            std::cout << token << std::endl;
            a.erase(0, pos + delimiter.length());
        }
        char firstA = a[0];
        a.erase(0, 1);
        
        std::cout << a + firstA + c  << std::endl;
    }
    

    不确定高级程序员是否会反对该解决方案... 再次:非常感谢!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-06-06
      • 2010-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-03-10
      相关资源
      最近更新 更多