Question

Il y avait un commentaire passager dans un de mes livres à propos de personnes entrant des virgules dans des nombres entiers et gâchant votre programme, mais il n'était pas détaillé.Cela m'a fait réfléchir, alors j'ai essayé d'écrire un petit algorithme pour prendre une chaîne std::string et supprimer tous les caractères non entiers.Ce code compile mais ignore la sortie.Pourquoi rien n’est-il attribué à newstring ?Est-ce que if(isdigit(fstring[i])) est évalué à true pour l'adresse vers laquelle il pointe pour contenir un chiffre ?

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

Question secondaire, qui appartient peut-être à ailleurs :comment convertir une chaîne en entier (ou en nombre à virgule flottante) ?

Était-ce utile?

La solution

newstring est de longueur 0, donc newstring[x] où x=0 est en fait illégal.Vous devez ajouter à la chaîne en utilisant :nouvellechaîne.append(1, fstring[i])

Pour la question secondaire, recherchez les fonctions atoi(), atof(), strtol(0, strtof().

Autres conseils

Les chaînes sont comme des tableaux, mais le constructeur par défaut d'une chaîne crée une chaîne vide.Pourquoi devrait-il allouer plus de mémoire que nécessaire ?Même si c'est le cas, on ne sait pas combien, ni s'il sera suffisamment grand pour une copie filtrée de fstring.Je suis impressionné qu'il ne plante pas.

Une modification simple serait de changer :

std::string newstring;

à:

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

Et après la boucle, ajoutez :

 newstring.resize(x);

Cela garantira que newstring aura au moins assez de place (probablement plus) pendant la filtration et sera réduit à la taille appropriée lorsque vous aurez fini de filtrer.Vous pourriez également être intéressé par le std::remove_copy_if fonctionner dans <algorithm>.

Par exemple.

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

Quant à la conversion d'une chaîne en entier/float, en plus de atoi, strtol, atof, strtof, etc.fonctions déjà mentionnées, vous pouvez également utiliser la bibliothèque 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;

De plus, si vous êtes familier avec la famille de fonctions printf, cela pourrait vous intéresser scanf, sscanf

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

Développement de la réponse de Shing Yip :

Pour supprimer les non-chiffres :

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

Cependant, je ne sais pas pourquoi ce static_cast est nécessaire.Je pense que quelque chose est ambigu à propos de isdigit sans lui.[Modifier:Si vous ne faites pas "en utilisant l'espace de noms std", alors vous n'en avez pas besoin, c'est donc ma faute si j'ai été paresseux en écrivant un exemple de code.]

On peut se demander si cela est plus simple que de lancer votre propre boucle :

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

Et C++0x aura copy_if, qui a été laissé de côté par accident, et qui est simple à implémenter :

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

Pour convertir en int (ou float):

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

Ou si vous n'avez pas de boost :

#include <sstream>

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

Notez que vous devez initialiser i, sinon il ne sera pas défini si fstring est vide.

Pour supprimer des chiffres :

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

Pour convertir une chaîne en int/float/... :

int n1 = boost::lexical_cast<int>("123");
float n2 = boost::lexical_cast<float>("123.456");
  • chaîne en nombre à virgule flottante :

Vous devez #include <cstdlib>

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

Par exemple:

 float f = strtof("3.4",NULL);
  • chaîne en entier

Vous devez #include <cstdlib>

int atoi(const char *numPtr);

Notez qu'il s'agit de fonctions C, pas C++, vous devez donc utiliser la méthode c_str() sur std::string pour obtenir la chaîne C.

const char* c_str ( ) const;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top