【问题标题】:Ho to get a string till the last occurrence of a character何获取一个字符串,直到最后一次出现一个字符
【发布时间】:2020-10-25 13:21:09
【问题描述】:

编辑 1

我忘了说字符串必须取自cin

我有一个字符串,例如“Hi; my;; name is Andrea; and I like C++”。 我想创建一个用该字符串初始化的字符串流,并在最后一个 ; 之前获取所有内容。

这是我尝试过的:

    string ex("Hi; my;; name is Andrea;; and I like C++"), text, final_text;
    stringstream loop_stream(ex);
    int findComma = loop_stream.str().find(';');
    do {
        getline(loop_stream, text, ';');
        loop_stream.ignore(1);
        final_text += text;
        loop_stream << loop_stream.rdbuf();
        findComma = loop_stream.str().find(';');
        while (findComma == 1) {
            loop_stream.ignore(1);
        }
        findComma = loop_stream.str().find(';');
    }
    while (findComma != string::npos);

    cout << "-" << final_text << "-" << endl;

但它根本不起作用......我希望输出是:

-Hi; my;; name is Andrea-

【问题讨论】:

  • 为什么要做那些复杂的事情而不是仅仅搜索最后一个';'使用string::rfind 然后使用string::substr 获取预期的子字符串?
  • 我认为 OP 不知道您可以从字符串末尾向后进行搜索。
  • 如果您创建一个函数来解决问题,则字符串的来源没有区别。也许这也是您的代码比应有的复杂得多的原因——您试图编写将输入例程与字符串操作混合的代码。

标签: c++ string stream stringstream


【解决方案1】:

您可以使用istreambuf_iteratoristream 中的所有内容构造string(如std::cin)。之后,只需使用其他答案之一来提取您想要的内容:

#include<iostream>
#include<iterator>
#include<sstream>

int main(){
    std::istringstream loop_stream("Hi; my;; name is Andrea;; and I like C++");

    // read the stream until it's depleted and put it in a string:
    std::string all_stream(std::istreambuf_iterator<char>(loop_stream),
                           std::istreambuf_iterator<char>{});

    // use any of the other answers, like this:

    std::string final_text;
    if(auto pos = all_stream.find_last_of(";"); pos != all_stream.npos) {
        final_text = all_stream.substr(0, pos);
    }

    std::cout << '-' << final_text << "-\n";
}

输出:

-Hi; my;; name is Andrea-

【讨论】:

    【解决方案2】:

    您被困在重复循环中,请检查您的循环条件。我认为 findComma 存在一些问题,它的值没有更新。

    【讨论】:

    • 这是评论,不是答案。
    【解决方案3】:

    这是另一个使用find_last_of的解决方案:

    #include <string>
    #include <iostream>
    
    int main()
    {
       std:: string test = "Hi; my;; name is Andrea; and I like C++";
       auto pos = test.find_last_of(";");
       if ( pos != std::string::npos)
          std::cout << test.substr(0, pos);
    }
    

    输出:

    Hi; my;; name is Andrea
    

    使用函数:

    #include <string>
    #include <iostream>
    
    std::string parseString(const std::string& s)
    {
       auto pos = s.find_last_of(";");
       if ( pos != std::string::npos)
          return s.substr(0, pos);
       return s;
    } 
    
    int main()
    {
       std::cin >> test;  // assume the string will be inputed
       std::cout << parseString(test);
    }
    

    【讨论】:

    • 谢谢,但我刚刚意识到我写了一个与我的想法不同的问题,我需要从cin中获取字符串
    • 字符串的来源无关紧要。获取我发布的代码,使其成为返回std::string 的函数,然后使用输入字符串调用该函数。
    • 如果用户想开始一个新行,这也适用吗?
    • 编程中有一个设计原则叫做separation of concerns。您尝试解析的输入字符串来自何处或如何来并不重要。该函数只做一件事——获取一个包含所有这些分号的字符串,并将结果返回给调用者。它不关心它接收到的字符串是在何处、何时或如何产生的。正如我在主要部分中的评论所指出的,这可能就是您的原始解决方案过于复杂的原因。
    【解决方案4】:

    不使用 stringstream 的更简单的东西怎么样:

    string ex("Hi; my;; name is Andrea;; and I like C++");
    size_t pos = ex.rfind(';'); // find last semicolon
    string final_text = ex.substr(0, pos);
    

    【讨论】:

    • 谢谢,但我刚刚意识到我写了一个与我的想法不同的问题,我需要从cin获取字符串
    • @JohnBardeen:好的,然后使用std::getline()cin 获取整个字符串,然后应用我的解决方案。
    • 如果我错了,请纠正我,但如果字符串可以包含换行符,我就不能这样做
    • 您可以重复调用 getline() (我最喜欢的方法),或者调用 cin.read() 将最大长度的可能输入到单个缓冲区中(在这种情况下,您必须知道最大长度在提前)。
    • 我要求的所有这些东西都是针对我的教授给出的一个项目......用户应该能够在编写整个命令时编辑它......
    猜你喜欢
    • 2014-03-04
    • 2020-09-17
    • 1970-01-01
    • 2021-08-22
    • 1970-01-01
    • 1970-01-01
    • 2022-01-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多