Pregunta

Así que actualmente estoy aprendiendo C ++ y decidí hacer un programa que pruebe mis habilidades que he aprendido hasta ahora. Ahora, en mi código, quiero verificar si el valor que ingresa el usuario es un doble, si no es un doble, pondré un bucle if y les pediré que lo vuelvan a ingresar. El problema que tengo es cómo hago para verificar qué tipo de variable ingresa el usuario, por ejemplo, si un usuario ingresa un carácter o una cadena, puedo enviar un mensaje de error. Aquí está mi código:

//cubes a user entered number
#include <iostream>
using namespace std;

double cube(double n); //function prototype

int main()
{
    cout << "Enter the number you want to cube: "; //ask user to input number
    double user;
    cin >> user;  //user entering the number

    cout << "The cube of " << user << " is " << cube(user) << "." << endl; //displaying the cubed number

    return 0;
}

double cube (double n) //function that cubes the number
{
    return n*n*n; // cubing the number and returning it
}

Editar: Debo decir que acabo de comenzar y no tengo la menor idea sobre su código, pero revisaré su enlace. Por cierto, todavía no he aprendido a trabajar con plantillas, estoy aprendiendo sobre el manejo de datos, solo el Capítulo 3 en mi C ++ Primer Plus 5ta edición.

¿Fue útil?

Solución

No hay una forma adecuada de verificar si una cadena realmente contiene un doble dentro de la biblioteca estándar. Probablemente desee utilizar Boost . La siguiente solución está inspirada en la receta 3.3 en C ++ Cookbook :

#include <iostream>
#include <boost/lexical_cast.hpp>
using namespace std;
using namespace boost;

double cube(double n);

int main()
{
    while(true)
    {
        cout << "Enter the number you want to cube: ";
        string user;
        cin >> user;

        try
        {
            // The following instruction tries to parse a double from the 'user' string.
            // If the parsing fails, it raises an exception of type bad_lexical_cast.
            // If an exception is raised within a try{ } block, the execution proceeds
            // with one of the following catch() blocks
            double d = lexical_cast <double> (user);   

            cout << "The cube of " << d << " is " << cube(d) << "." << endl;
            break;
        }
        catch(bad_lexical_cast &e)
        {
            // This code is executed if the lexical_cast raised an exception; We
            // put an error message and continue with the loop
            cout << "The inserted string was not a valid double!" << endl;
        }
    }
    return 0;
}

double cube (double n)
{
    return n*n*n;
}

Otros consejos

Forma segura de C ++

Puede definir una función para esto usando std :: istringstream :

#include <sstream>  

bool is_double(std::string const& str) {
    std::istringstream ss(str);

    // always keep the scope of variables as close as possible. we see
    // 'd' only within the following block.
    {
        double d;
        ss >> d;
    }

    /* eat up trailing whitespace if there was a double read, and ensure
     * there is no character left. the eof bit is set in the case that
     * `std::ws` tried to read beyond the stream. */
    return (ss && (ss >> std::ws).eof());
}

Para ayudarlo a descubrir qué hace (algunos puntos se simplifican):

  • Creación de un flujo de cadena de entrada inicializado con la cadena dada
  • Lectura de un valor doble usando operator > > . Esto significa omitir espacios en blanco e intentar leer un doble.
  • Si no se puede leer el doble, como en abc , la secuencia establece el bit fail . Tenga en cuenta que casos como 3abc tendrán éxito y no establecerán el bit de error.
  • Si se establece el bit de falla, ss se evalúa a un valor cero, lo que significa falso .
  • Si se leyó un doble, omitimos los espacios en blanco finales. Si estamos al final de la secuencia (tenga en cuenta que eof () devolverá verdadero si intentamos leer más allá del final. std :: ws hace exactamente eso), eof devolverá verdadero. Tenga en cuenta que esta verificación se asegura de que 3abc no pasará nuestra verificación.
  • Si ambos casos, a la derecha y a la izquierda del & amp; & amp; se evalúan como verdadero , devolvemos verdadero al llamador, indicando que la cadena dada es un doble.

Similar, verifica int y otros tipos. Si sabe cómo trabajar con plantillas, también sabe cómo generalizar esto para otros tipos. Por cierto, esto es exactamente lo que boost :: lexical_cast le proporciona. Compruébelo: http://www.boost.org/ doc / libs / 1_37_0 / libs / conversion / lexical_cast.htm .

C Way One

Esta manera tiene ventajas (ser rápido) pero también desventajas importantes (no se puede generalizar usando una plantilla, necesita trabajar con punteros sin procesar):

#include <cstdlib>
#include <cctype>  

bool is_double(std::string const& s) {
    char * endptr;
    std::strtod(s.c_str(), &endptr);
    if(endptr != s.c_str()) // skip trailing whitespace
        while(std::isspace(*endptr)) endptr++;
    return (endptr != s.c_str() && *endptr == '\0');
}

strtod establecerá endptr en el último carácter procesado. Que es en nuestro caso el carácter nulo de terminación. Si no se realizó ninguna conversión, endptr se establece en el valor de la cadena dada a strtod .

C Way Two

Una cosa podría ser que std :: sscanf hace el truco. Pero es fácil supervisar algo. Aquí está la forma correcta de hacerlo:

#include <cstdio>

bool is_double(std::string const& s) {
    int n;
    double d;
    return (std::sscanf(s.c_str(), "%lf %n", &d, &n) >= 1 && 
            n == static_cast<int>(s.size()));
}

std :: sscanf devolverá los elementos convertidos. Aunque el Estándar especifica que % n no está incluido en ese recuento, varias fuentes se contradicen entre sí. Lo mejor es comparar > = para hacerlo bien (consulte la página de manual de sscanf ). n se establecerá en la cantidad de caracteres procesados. Se compara con el tamaño de la cadena. El espacio entre los dos especificadores de formato representa el espacio en blanco final opcional.

Conclusión

Si es un principiante, lea en std :: stringstream y hágalo de la manera C ++. Mejor no te metas con los punteros hasta que te sientas bien con el concepto general de C ++.

sscanf puede hacer lo que quiera; devuelve el número de argumentos procesados ??correctamente. Esto debería ayudarlo a comenzar:

//cubes a user entered number
#include <iostream>
#include <cstdio>
using namespace std;

double cube(double n); //function prototype

int main()
{
        cout << "Enter the number you want to cube: "; //ask user to input number
        string user;
        cin >> user;  //user entering the number

        // Convert the number to a double.
        double value;
        if(sscanf(user.c_str(), "%lf", &value) != 1)
        {
                cout << "Bad!  " << user << " isn't a number!" << endl;
                return 1;
        }

        cout << "The cube of " << user << " is " << cube(user) << "." << endl; //displaying the cubed number

        return 0;
}

double cube (double n) //function that cubes the number
{
        return n*n*n; // cubing the number and returning it
}

Otros métodos publicados en otras respuestas tienen sus ventajas y desventajas. Este tiene problemas con los caracteres finales y no es "C ++" -y.

Debo decir que acabo de empezar y no tengo la menor idea de tu código, pero revisaré tu enlace. Por cierto, todavía no he aprendido a trabajar con plantillas, estoy aprendiendo sobre el manejo de datos, solo el Capítulo 3 en mi C ++ Primer Plus 5ta edición.

Puede recurrir a C y usar strtod

Tu programa lee en una cadena y luego la pasa a una función que intenta convertir la cadena en doble.

bool is_double(const char* strIn, double& dblOut) {
    char* lastConvert = NULL;
    double d = strtod(strIn, &lastConvert);
    if(lastConvert == strIn){
        return false;
    } else {
       dblOut = d;
       return true;
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top