Pregunta

Hubo un comentario pasajero en un libro mío sobre personas que ingresaban comas en números enteros y estropeaban su programa, pero no daba más detalles.Eso me hizo pensar, así que intenté escribir un pequeño algoritmo para tomar una cadena std:: y eliminar todos los caracteres que no sean enteros.Este código se compila pero omite el resultado.¿Por qué no se asigna nada a la nueva cadena?¿If(isdigit(fstring[i])) se evalúa como verdadero de la dirección a la que apunta para contener un dígito?

//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");
}

Pregunta secundaria, que quizás pertenezca a otra parte:¿Cómo se convierte una cadena en un int (o un número de punto flotante)?

¿Fue útil?

Solución

la cadena de noticias es de longitud 0, por lo que la cadena de noticias [x] donde x = 0 es realmente ilegal. Debe agregar a la cadena usando: newstring.append (1, fstring [i])

Para la pregunta secundaria, busque las funciones atoi (), atof (), strtol (0, strtof ().

Otros consejos

Las cadenas son como matrices, pero el constructor predeterminado para una cadena crea una cadena vacía. ¿Por qué debería asignar más memoria de la que necesita? Incluso si lo hace, no se sabe cuánto, o si será lo suficientemente grande para una copia filtrada de fstring. Estoy impresionado de que no se bloquee.

Una modificación simple sería cambiar:

std::string newstring;

a:

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

Y después del ciclo agregue:

 newstring.resize(x);

Esto asegurará que newstring tendrá al menos suficiente espacio (probablemente más) durante la filtración y se recortará al tamaño apropiado cuando termine de filtrar. También puede estar interesado en la función std::remove_copy_if en <algorithm>.

Por ejemplo

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());

En cuanto a convertir una cadena en un entero / flotante, además de las funciones atoi, strtol, atof, strtof, etc. ya mencionadas, también puede hacer uso de la biblioteca 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;

Además, si está familiarizado con la familia de funciones printf, puede estar interesado en scanf, sscanf

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

Expansión en la respuesta de Shing Yip:

Para eliminar no dígitos:

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

No estoy seguro de por qué se necesita esa static_cast. Creo que algo es ambiguo sobre isdigit sin él. [Editar: si no haces & Quot; usando el espacio de nombres std & Quot; entonces no lo necesitas, así que es mi culpa por ser vago escribiendo código de ejemplo.]

Es discutible si esto es más simple que rodar tu propio bucle:

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

Y C ++ 0x tendrá copy_if, que se omitió básicamente por accidente, y es trivial de implementar:

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

Para convertir a int (o flotante):

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

O si no tienes impulso:

#include <sstream>

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

Tenga en cuenta que debe inicializar i, de lo contrario no se establecerá si fstring está vacío.

Para eliminar dígitos:

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

Para convertir una cadena a int / float / ...:

int n1 = boost::lexical_cast<int>("123");
float n2 = boost::lexical_cast<float>("123.456");
  • cadena al número de coma flotante:

Necesitas #include <cstdlib>

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

Por ejemplo:

 float f = strtof("3.4",NULL);
  • cadena a entero

Necesitas <=>

int atoi(const char *numPtr);

Observe que estas son funciones C, no C ++, por lo que debe utilizar el método c_str () en std :: string para obtener la cadena C

const char* c_str ( ) const;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top