Domanda

Quindi attualmente sto imparando il C ++ e ho deciso di creare un programma che metta alla prova le mie abilità che ho imparato finora. Ora nel mio codice voglio verificare se il valore inserito dall'utente è un doppio, se non è un doppio inserirò un ciclo if e chiederò loro di rientrare. Il problema che ho è come posso verificare il tipo di variabile immessa dall'utente, ad esempio se un utente immette un carattere o una stringa, posso emettere un messaggio di errore. Ecco il mio codice:

//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
}

Modifica: dovrei dire che ho appena iniziato e non ho la minima idea del tuo codice, ma controllerò il tuo link. A proposito, non ho ancora imparato a lavorare con i modelli, sto imparando a gestire i dati, solo il capitolo 3 della mia C ++ Primer Plus 5a edizione.

È stato utile?

Soluzione

Non esiste un modo adatto per verificare se una stringa davvero contiene un doppio all'interno della libreria standard. Probabilmente vuoi usare Boost . La seguente soluzione è ispirata alla ricetta 3.3 del Cookbook C ++ :

#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;
}

Altri suggerimenti

Modo C ++ sicuro

Puoi definire una funzione per questo 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());
}

Per aiutarti a capire cosa fa (alcuni punti sono semplificati):

  • Creazione di un input-stringstream inizializzato con la stringa fornita
  • Leggendo un doppio valore da esso usando operator > > . Questo significa saltare gli spazi bianchi e provare a leggere un doppio.
  • Se non è possibile leggere il doppio, come in abc il flusso imposta il bit fail . Si noti che casi come 3abc avranno esito positivo e non imposterà il bit di errore.
  • Se il bit di errore è impostato, ss restituisce un valore zero, che significa false .
  • Se viene letto un doppio, saltiamo gli spazi bianchi finali. Se poi siamo alla fine dello stream (nota che eof () restituirà true se provassimo a leggere oltre la fine. std :: ws fa esattamente questo), eof restituirà true. Nota che questo controllo assicura che 3abc non passerà il nostro controllo.
  • Se entrambi i casi, a destra ea sinistra di & amp; & amp; valutano true , restituiamo true al chiamante, segnalando che la stringa data è doppia.

Simile, controlli int e altri tipi. Se sai come lavorare con i template, sai come generalizzare questo anche per altri tipi. Per inciso, questo è esattamente ciò che boost :: lexical_cast ti offre. Dai un'occhiata: http://www.boost.org/ doc / libs / 1_37_0 / librerie / conversione / lexical_cast.htm .

C Way One

In questo modo presenta vantaggi (essendo veloce) ma anche importanti svantaggi (non è possibile generalizzare utilizzando un modello, è necessario lavorare con puntatori non elaborati):

#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 imposterà endptr sull'ultimo carattere elaborato. Che è nel nostro caso il carattere null terminante. Se non è stata eseguita alcuna conversione, endptr è impostato sul valore della stringa fornita a strtod .

C Way Two

Si potrebbe pensare che std :: sscanf faccia il trucco. Ma è facile supervisionare qualcosa. Ecco il modo corretto di farlo:

#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 restituirà gli articoli convertiti. Sebbene lo standard specifichi che % n non è incluso in quel conteggio, diverse fonti si contraddicono a vicenda. È il migliore per confrontare > = per farlo bene (vedi la manpage di sscanf ). n verrà impostato sulla quantità di caratteri elaborati. Viene confrontato con la dimensione della stringa. Lo spazio tra i due identificatori di formato tiene conto degli spazi bianchi finali opzionali.

Conclusione

Se sei un principiante, leggi in std :: stringstream e fallo in modo C ++. Meglio non scherzare con i puntatori finché non ti senti bene con il concetto generale di C ++.

sscanf può fare quello che vuoi; restituisce il numero di argomenti correttamente elaborati. Questo dovrebbe iniziare:

//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
}

Altri metodi pubblicati in altre risposte hanno i loro vantaggi e svantaggi. Questo ha problemi con i caratteri finali e non è " C ++ " -y.

Devo dire che ho appena iniziato e non ho la minima idea del tuo codice, ma controllerò il tuo link. A proposito, non ho ancora imparato a lavorare con i modelli, sto imparando a gestire i dati, solo il capitolo 3 della mia C ++ Primer Plus 5a edizione.

Puoi tornare su C e utilizzare strtod

Il programma legge in una stringa e quindi lo passa a una funzione che tenta di convertire la stringa in doppio.

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;
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top