Limit user input to certain characters

1

This is the implementation for a program that basically converts from DNA to RNA. The bases can only be GTAC, and when transcribed is GUAC, or just change the T for the U. How to do so that when the user inserts other letters that are not those the program does not run or put an error message in the bases? I attach the code:

#include <iostream>
#include <cstring>
using namespace std; 
class ADN {
   private:
      string secuencia;
   public:
      ADN(string _secuencia);
      string GetSecuencia();
      int Longitud();
      string Transcripcion();
      string GetTranscripcion();

};

ADN::ADN(string _secuencia){
    secuencia=_secuencia;
}
string ADN::GetSecuencia(){
    return secuencia;
}

int ADN::Longitud(){
  return secuencia.length();
}
string ADN::Transcripcion() {
  string out = ""; // Realmente no se si esta bien :p
  for (int i = 0; i <= secuencia.length(); i++)
    out += (secuencia[i] == 'T')? 'U': secuencia[i];
  return out;
}

int main() {
  string Secuencia_ADN = "";               
  cout << "Inserte secuencia de ADN: ";
  cin >> Secuencia_ADN;

  ADN a1(Secuencia_ADN);                   
  cout << "La secuencia de ADN es:" << a1.GetSecuencia() << endl;
  cout << "La longitud de la secuencia es:" << a1.Longitud() << endl;
  cout << "La secuencia de ARN es: " << a1.Transcripcion() << endl;

  system("pause");
  return 0;
}
    
asked by Asiel Cabrera Guerrero 29.05.2018 в 22:51
source

1 answer

2

To show a reading error, just analyze what you read:

std::string Secuencia_ADN = "";               
std::cout << "Inserte secuencia de ADN: ";
std::cin >> Secuencia_ADN;

for (const auto &base : Secuencia_ADN) {
    switch(base) {
        case 'G': case 'T': case 'A': case 'C':
        case 'g': case 't': case 'a': case 'c':
            break;
        default:
            std::cout << base << " no es una base de ADN\n";
            return 1;
    }
}

If you add the previous code to your function main the return 1 will cause the program to end informing the operating system that something did not go well (that is what is interpreted for returns different from 0 ).

Proposal.

I, personally, would overload the data injection operator ( >> ) in the class that handles sequences:

struct ADN {
      ADN(string _secuencia);
      string GetSecuencia();
      int Longitud();
      string Transcripcion();
      string GetTranscripcion();
      friend std::istream &operator >>(std::istream &i, ADN &adn);
   private:
      string secuencia;    
};

std::istream &operator >>(std::istream &i, ADN &adn) {
    std::string datos;
    i >> datos;

    for (const auto &d : datos) {
        switch(d) {
            case 'G': case 'T': case 'A': case 'C':
            case 'g': case 't': case 'a': case 'c':
                break;
            default:
                throw std::invalid_argument{datos};
        }
    }

    adn = ADN{datos};
}

If an incorrect sequence is inserted, an exception of std::invalid_argument will be thrown. In this way, you could read sequences directly from the console:

int main() {
    ADN a1("");
    cout << "Inserte secuencia de ADN: ";

    try {
        cin >> a1;

        cout << "La secuencia de ADN es:" << a1.GetSecuencia() << endl;
        cout << "La longitud de la secuencia es:" << a1.Longitud() << endl;
        cout << "La secuencia de ARN es: " << a1.Transcripcion() << endl;
    } catch(const std::invalid_argument &e) {
        cout << "Secuencia no valida: " << e.what() << '\n';
    }

    return 0;
}
    
answered by 30.05.2018 / 07:54
source