首页 > 解决方案 > 如何从以前使用多个 cout 打印的内容中删除子字符串?

问题描述

编辑:补充说这基本上是我希望它的工作方式:

用户输入#1:

(#1 选项 1a)(#1 选项 1b)

(#1 选项 2a)(#1 选项 2b)

(#1 选项 3a)(选项 3b)

用户输入#2:

(#2 选项 1a)(#2 选项 1b)

(#2 选项 2a)(#2 选项 2b)

(#2 选项 3a)(#2 选项 3b)

从用户输入#1,有一个

从用户输入#2,有一个

如果随机掷出的几率超过 100 次中的 50 次,则选择“a”。如果随机滚动的机会等于或小于 100 的 50,则选择“b”。

(#1 随机选择第一个基因 a 或 b)(#2 随机选择第一个基因 a 或 b)

(#1 随机选择第二个基因 a 或 b)(#2 随机选择第二个基因 a 或 b)

(#1 随机选择第三个基因 a 或 b)(#2 随机选择第三个基因 a 或 b)

等等等等。


几天前,我刚开始使用 c++ 进行编码,并且开始着手这个项目以开始工作。

到目前为止它已经奏效,但我遇到了一个问题,我想从以前的 cout(s) 的结果中删除一个子 (?) 字符串 "nn"。但是,由于它已经打印到控制台,我不认为我可以编辑它。有没有办法解决?

这个项目是一个“RNG”滚轮,对于那些熟悉 MMO 的人来说,可能知道如果玩家即将收到战利品,游戏会随机决定你得到什么。

在这个项目中,我让用户输入父母马的遗传密码(基因型),并根据父母的可能性,让它随机生成小马驹(小马)的基因型。(我希望这是有道理的。)

我试过添加

start_position_to_erase = find("nn");
erase(start_position_to_erase, 2);

最后删除由于基因“D”(dun)不存在于父母的基因和随后的小马驹中而弹出的任何“nn”,但它会吐出关于如何指定的错误字符串,以便它可以从该字符串中删除。

#include <iostream>
#include <algorithm>
#include <string>
#include <cstdlib>
#include <ctime>
#include <vector>
using namespace std;

int main(){
string mgenotype, sgenotype, start_position_to_erase;

vector<std::string> Mchance = {"E", "A", "D", "Cr", "Ch", "Z", "G", "O", "To", "Sb", "W", "Rn", "Spl", "Prl"};
vector<std::string> Schance = {"E", "A", "D", "Cr", "Ch", "Z", "G", "O", "To", "Sb", "W", "Rn", "Spl", "Prl"};

cout << "Enter the mare's genotype: "; getline(cin, mgenotype);
cout << "Enter the sire's genotype: "; getline(cin, sgenotype);

srand((int)time(0));

// "A" (and it's variants "At" and "A+") gene MARE ----------------------------------------------------------------
if (mgenotype.find ("AtAt") != string::npos){ cout << "At" ;}
else if (mgenotype.find ("A+A+") != string::npos){ cout << "A+" ;}
else if (mgenotype.find ("AA") != string::npos){ cout << "A";}
else if (mgenotype.find ("aa") != string::npos){ cout << "a";}

else if (mgenotype.find ("Ata") != string::npos || mgenotype.find ("aAt" ) != string::npos){
    Mchance[1] = (rand() % 100);
    if (Mchance[1] <= "50") { cout << "At" ;}
    else { cout << "a" ;}}

else if (mgenotype.find ("A+a") != string::npos || mgenotype.find ("aA+") != string::npos){
    Mchance[1] = (rand() % 100);
    if (Mchance[1] <= "50") { cout << "A+" ;}
    else { cout << "a" ;}}

else if (mgenotype.find ("Aa") != string::npos || mgenotype.find ("aA")!= string::npos) {
    Mchance[1] = (rand() % 100);
    if (Mchance[1] <= "50") { cout << "A" ;}
    else { cout << "a" ;}}

else {}

// "A" (and it's variants "At" and "A+") gene SIRE ----------------------------------------------------------------
if (sgenotype.find ("AtAt") != string::npos){ cout << "At" ;}
else if (sgenotype.find ("A+A+") != string::npos){ cout << "A+" ;}
else if (sgenotype.find ("AA") != string::npos){ cout << "A";}
else if (sgenotype.find ("aa") != string::npos){ cout << "a";}

else if (sgenotype.find ("Ata") != string::npos || sgenotype.find ("aAt") != string::npos){
    Schance[1] = (rand() % 100);
    if (Schance[1] <= "50") { cout << "At" ;}
    else { cout << "a" ;}}

else if (sgenotype.find ("A+a") != string::npos || sgenotype.find ("aA+") != string::npos){
    Schance[1] = (rand() % 100);
    if (Schance[1] <= "50") { cout << "A+" ;}
    else { cout << "a" ;}}

else if (sgenotype.find ("Aa") != string::npos || sgenotype.find ("aA")!= string::npos) {
    Schance[1] = (rand() % 100);
    if (Schance[1] <= "50") { cout << "A" ;}
    else { cout << "a" ;}}

else {}

cout << " ";

// "D" gene MARE ----------------------------------------------------------------
if (mgenotype.find ("DD") != string::npos){ cout << "D" ;}
else if (mgenotype.find ("nn") != string::npos || mgenotype.find ("")!= string::npos ){ cout << "n";}

else if (mgenotype.find ("Dn") != string::npos || mgenotype.find ("nD") != string::npos) {
    Mchance[2] = (rand() % 100);
    if (Mchance[2] <= "50") { cout << "D" ;}
    else { cout << "n" ;}}

else {}

// "D" gene SIRE ----------------------------------------------------------------
if (sgenotype.find ("DD") != string::npos){ cout << "D" ;}
else if (sgenotype.find ("nn") != string::npos || sgenotype.find ("") != string::npos){ cout << "n";}

else if (sgenotype.find ("Dn") != string::npos || sgenotype.find ("nD") != string::npos) {
    Schance[2] = (rand() % 100);
    if (Schance[2] <= "50") { cout << "D" ;}
    else { cout << "n" ;}}

else {}

cout << " ";

正如你从vector<std::string> Mchance = {andSchance行看到的,我有很多我想在最后添加的基因列表,如果有 12 个或更多的“nn”会很烦人而且不整洁。

更糟糕的是,如果中间有一个基因传给了小马驹,而其余的则没有,那将很难阅读。因此,我只想保留那些将基因传递给它的小马驹的基因。

我有一种感觉,我必须将代码打印到文件并从那里编辑,但我也不知道该怎么做。

任何帮助或指示将不胜感激。谢谢!

标签: c++string

解决方案


我真的不清楚您希望做什么,而且您的代码很难阅读,但我很无聊,所以我想出了一些既简单又可以解决您在显示之前有条件地构建输出的问题.

#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <iostream>
#include <map>
#include <sstream>
#include <string>
#include <vector>

struct ConditionalReplacement
{
    int threshold;
    std::string choices[2];
};

std::map<std::string, std::string> simple_replacements =
{
    {"AtAt", "At"},
    {"A+A+", "A+"},
    {"AA", "A"},
    {"aa", "a"},
    {"DD", "D"},
    {"nn", "n"},
};

std::map<std::string, ConditionalReplacement> conditional_replacements =
{
    {"Ata", {50, "At", "a"}},
    {"aAt", {50, "At", "a"}},
    {"A+a", {50, "A+", "a"}},
    {"aA+", {50, "A+", "a"}},
    {"Aa", {50, "A", "a"}},
    {"aA", {50, "A", "a"}},
    {"Dn", {50, "D", "n"}},
    {"nD", {50, "D", "n"}},
};

void HandleReplacements(const std::string &in, std::stringstream &out, const std::string &default_for_empty_src)
{
    if (in.empty())
    {
        out << std::right << std::setw(6) << ("'" + in + "'")
            << std::left << " = " << ("'" + default_for_empty_src + "'");
        return;
    }
    for (const auto &item : simple_replacements)
    {
        if (in.find(item.first) != std::string::npos)
        {
            out << std::right << std::setw(6) << ("'" + in + "'")
                << std::left << " = " << ("'" + item.second + "'");
            return;
        }
    }
    for (const auto &item : conditional_replacements)
    {
        if (in.find(item.first) != std::string::npos)
        {
            int r = rand() % 100;
            int index = 1 - (r <= item.second.threshold);
            out << "r = " << std::setw(2) << r << " : " << std::right << std::setw(6) << ("'" + in + "'")
                << std::left << " = " << ("'" + item.second.choices[index] + "'");
            return;
        }
    }
}

int main()
{
    srand((int)time(0));

    std::string mgenotypes[] = { "AtAt", "AA", "DD", "", "Ata", "A+a", "Aa", "Dn" };
    std::string sgenotypes[] = { "", "A+A+", "aa", "nn", "aAt", "aA+", "aA", "nD" };
    std::stringstream output;

    for (const auto &mgenotype : mgenotypes)
    {
        HandleReplacements(mgenotype, output, "n");
        std::cout << output.str() << "\n";
        output.str("");
    }
    for (const auto &sgenotype : sgenotypes)
    {
        HandleReplacements(sgenotype, output, "n");
        std::cout << output.str() << "\n";
        output.str("");
    }

    return 0;
}

既然你说你几天前刚刚开始使用 C++,这可能会让人不知所措,我不会解释每一行,但我会尝试解释这些概念。

如果您发现自己重复了很多非常相似的代码,请不要继续这样做。看看为什么要重复该代码,并尝试将其抽象为一个函数或一系列函数。关于 DRY 原则的维基百科文章有一些链接到其他有关此的阅读最好的资料来源,IMO,是 The Pragmatic Programmer 一书。我向没有读过它的人推荐它。

std::map和其他关联容器很棒。如果您需要用其他东西替换某些东西,只需添加源作为键并将替换作为值,并且您有一个即时查找表,您可以迭代或搜索。将它与完成工作的功能结合起来,您可能已经接近所有设置。

没有时间机器可以轻松让您返回并更改先前的输出,但您不需要它。相反,收集生成输出所需的所有数据,然后一次生成所有数据。std::stringstream在简单的情况下可能会对此有所帮助,但即便如此,您也不能轻易倒退,因此您可能会考虑根本不做任何输出,而只是将所有数据放入模型中,当模型完整且准确时您可以输出.

无论如何,我还是使用了 stringstream,主要是因为我不确定你的最终目标是什么。

无论如何,也许这会有所帮助。将来,如果您需要帮助,我希望您能提出更多问题,但请先花一些时间,并确保您已尽力解释所有内容,并且已将问题减少到可管理的范围内。通读如何创建 [mcve] 可以对此有所帮助。

祝你好运!


推荐阅读