Domanda

In un mio libro c'era un commento passeggero sulle persone che immettevano virgole in numeri interi e rovinavano il tuo programma, ma non è stato elaborato. Questo mi ha fatto pensare, quindi ho provato a scrivere un piccolo algoritmo per prendere uno std :: string e rimuovere tutti i caratteri non interi. Questo codice viene compilato ma salta l'output. Perché non viene assegnato nulla al newstring? If (isdigit (fstring [i])) valuta vero l'indirizzo che sta indicando per contenere una cifra?

//little algorithm to take the non-integers out of a string
//no idea on efficiency

#include <iostream>
#include <string>

int main()
{
    std::cout << "Enter a number with non-integer characters: ";

    std::string fstring; 
    getline(std::cin, fstring);

    std::string newstring;

    int i = 0, x = 0;

    while (i != fstring.length())
    {
        if (isdigit(fstring[i]))
        {
            newstring[x] = fstring[i];
            i++;
            x++;
        }
        else
        {
           i++;
        }
    }

    std::cout << std::endl;
    std::cout << newstring;
    system("PAUSE");
}

Domanda secondaria, che forse appartiene altrove: come si converte una stringa in un int (o un numero in virgola mobile)?

È stato utile?

Soluzione

il newstring è di lunghezza 0, quindi il newstring [x] dove x = 0 è in realtà illegale. Dovresti aggiungere alla stringa usando: newstring.append (1, fstring [i])

Per la domanda secondaria, cerca le funzioni atoi (), atof (), strtol (0, strtof ().

Altri suggerimenti

Le stringhe sono come matrici, ma il costruttore predefinito per una stringa crea una stringa vuota. Perché dovrebbe allocare più memoria del necessario? Anche se lo fa, non si può dire quanto, o se sarà abbastanza grande per una copia filtrata di fstring. Sono impressionato dal fatto che non si blocchi.

Una semplice modifica sarebbe quella di cambiare:

std::string newstring;

a:

 std::string newstring(fstring.length(), '\0')

E dopo il ciclo aggiungere:

 newstring.resize(x);

Ciò assicurerà che newstring disporrà di almeno uno spazio sufficiente (probabilmente maggiore) durante la filtrazione e verrà ridotto alla dimensione appropriata al termine del filtraggio. Potresti anche essere interessato alla std::remove_copy_if in <algorithm>.

per es.

struct isnotdigit { bool operator()(char c) { return !isdigit(c); } };

std::string newstring(fstring.length(), '\0');
std::string::iterator i = std::remove_copy_if(fstring.begin(), 
  fstring.end(), newstring.begin(), isnotdigit());
newstring.erase(i, newstring.end());

Per quanto riguarda la conversione di una stringa in un numero intero / float, oltre alle funzioni atoi, strtol, atof, strtof, ecc. già menzionate, puoi anche utilizzare la libreria iostream:

 #include <sstream>
 std::string integer("23");
 std::istringstream iss(integer);
 int result;
 iss >> result;

 std::string floatingpoint("3.14");
 std::istringstream iss2(floatingpoint);
 double result2;
 iss2 >> result2;

Inoltre, se hai familiarità con la famiglia di funzioni printf potresti essere interessato a scanf, sscanf

 const char *s = "23";
 int result;
 sscanf(s, "%d", &result);

Espansione sulla risposta di Shing Yip:

Per rimuovere le non cifre:

#include <iostream>
#include <functional>
#include <string>
#include <algorithm>

using namespace std;

int main() {
    string fstring;
    getline(cin, fstring);
    fstring.erase(
        remove_if(fstring.begin(), fstring.end(),
            not1(ptr_fun(static_cast<int(*)(int)>(isdigit)))
        ),
        fstring.end()
    );

    cout << fstring << "\n";
}

Non sono sicuro del motivo per cui sia necessario static_cast. Penso che qualcosa di ambiguo su isdigit senza di essa. [Modifica: se non si fa & Quot; usando lo spazio dei nomi std & Quot; allora non ne hai bisogno, quindi è colpa mia se sono pigro a scrivere il codice di esempio.]

È discutibile se questo sia più semplice che avviare il proprio loop:

#include <iostream>
#include <string>

using namespace std;

int main() {
    string fstring, ins;
    getline(cin, ins);
    for (string::iterator it = ins.begin(); it != ins.end(); ++it) {
        if (isdigit(*it)) fstring.push_back(*it);
    }
    cout << fstring << "\n";
}

E C ++ 0x avrà copy_if, che è stato praticamente escluso per caso, ed è banale da implementare:

#include <iostream>
#include <string>
#include <algorithm>
#include <iterator>

int main() {
    std::string fstring, ins;
    std::getline(std::cin, ins);
    std::copy_if(ins.begin(), ins.end(), 
        std::back_inserter(fstring), isdigit);
    std::cout << fstring << "\n";
}

Per convertire in int (o float):

int i = boost::lexical_cast<int>(fstring);

O se non hai boost:

#include <sstream>

int i = 0;
std::stringstream(fstring) >> i;

Nota che devi inizializzare i, altrimenti non sarà impostato se fstring è vuoto.

Per rimuovere le cifre:

fstring.erase(
      std::remove_if(fstring.begin(), fstring.end(), &isdigit), 
      fstring.end());

Per convertire la stringa in int / float / ...:

int n1 = boost::lexical_cast<int>("123");
float n2 = boost::lexical_cast<float>("123.456");
  • stringa in numero in virgola mobile:

Devi #include <cstdlib>

float strtof(const char *nptr, char **endptr);

Ad esempio:

 float f = strtof("3.4",NULL);
  • stringa in numero intero

Devi <=>

int atoi(const char *numPtr);

Nota che queste sono funzioni C, non C ++, quindi devi usare il metodo c_str () su std :: string per ottenere la C-string.

const char* c_str ( ) const;
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top