【问题标题】:how to limit string to have specific letters in C++ [closed]如何在 C++ 中限制字符串具有特定字母 [关闭]
【发布时间】:2021-12-05 14:49:45
【问题描述】:

所以基本上我制作了一个程序,它从用户那里获取一些输入并将其存储在变量中。但问题是我希望用户输入核苷酸 DNA 序列,并且由于 DNA 序列仅由字母 ATGC 组成,我想限制输入并且只包括这些字符,如果用户输入其他字符,则会显示错误

#include <iostream>
#include <string>

using namespace std;

int main ()
{
    string DNAsequence;
    cout<<"Enter the DNA sequence : ";
    cin>> DNAsequence;
    cout<< "Your 5 to 3 DNA sequence is "<<DNAsequence;
    
    
}

【问题讨论】:

  • 构建您自己的以std::string 为成员的类,并为std::istream 构建您自己的&gt;&gt; 运算符。考虑使用std::vectorenum 代替吗?您可以在这里玩得开心,并使用两个字节来存储每个核苷酸。
  • 你卡在哪里了?你的问题是什么?你已经达到了“我想做xxx”的程度。但随后您需要跟进“所以我尝试了 yyy,我期待 zzz,但实际发生的是 xyz”

标签: c++ string


【解决方案1】:

您可以循环使用cin.get()函数并检查输入字符

string GetStringFromConsole(){
    string Returner;
    char ch=0;

    while (ch = cin.get()){
        switch (ch){
        case 'A':
        case 'T':
        case 'G':
        case 'C':
            Returner += ch;
            break;
        case '\n':
        case '\r':
            break;
        default:
            cout << "Wrong input: " << ch << endl;
            cin.ignore(cin.rdbuf()->in_avail());
            Returner = "";
            break;
        }

        if (ch == '\n' || ch == '\r')
            break;
    }

    cout << Returner.data() << endl;
    return Returner;
}

【讨论】:

  • 如果Returner 为空,Returner.size() - 1 是邪恶的。
  • returner不能为空
  • 考虑计算一次 (Returnerner.size() - 1) 并将其放入临时变量中。您正在使用它 7 次,它只需要计算一次。与Returner[] 相同,请考虑放入单个 char 变量中。
  • Returnerner.size()每一步都不一样
  • @tho 编译器不需要那种帮助。 Returner.size() - 1evaluated 的频率不超过必要的频率。
【解决方案2】:

正如 Bathsheba 的评论中提到的,这听起来像是要在自定义 &gt;&gt; 重载中处理的事情。

首先让我们定义一个包含字符串并根据允许的字母参数化的类型:

template <char ...allowed_chars>
struct DNASequence {
    std::string value;
};

输出操作符很简单:

template <char ...allowed_chars>
std::ostream& operator<<(std::ostream& out,const DNASequence<allowed_chars...>& dna){
    out << dna.value;
    return out;
}

一个检查给定字母是否被允许的函数:

template <char ...allowed_chars>
bool check(char c){
    auto eq = [](char a,char b){ return a==b;};
    return (eq(c,allowed_chars) || ...);
}

现在输入运算符可以像往常一样读取一个字符串,然后检查该字符串的每个字符:

template <char ...allowed_chars>
std::istream& operator>>(std::istream& in, DNASequence<allowed_chars...>& dna){
    std::string temp;
    in >> temp;
    for (const auto& c : temp) {
        if (! check<allowed_chars...>(c)){
            in.setstate(std::ios::failbit);
            return in;
        }
    }
    dna.value = temp;
    return in;
}

Main 看起来像这样:

int main ()
{
    DNASequence<'A','C','G','T'> dna;
    std::cout << "Enter the DNA sequence : ";
    if (std::cin >> dna) {
        std::cout << "Your 5 to 3 DNA sequence is " << dna;
    } else {
        std::cout << "invalid input";
    }
}

我想您想重置std::cins 错误状态并使用循环再次询问用户,以防他们输入无效输入。

完整示例:https://godbolt.org/z/r4947G5sP

【讨论】:

  • 很好,点个赞。如果你能以某种方式安排事情会更好,所以DNASequence&lt;'A','C','G','T'&gt;DNASequence&lt;'C','A','G','T'&gt; 是同一类型!
  • @Bathsheba 我的第一个想法是重新排列它,以便我目前的DNASeuence 只是std::string&amp; 的包装器,仅充当“输入操纵器”以获得有效的@987654333 @。无论如何,还有很大的改进空间,例如使用枚举代替
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-01
  • 1970-01-01
  • 2020-02-28
  • 1970-01-01
  • 2011-08-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多