2015-09-27 1 views
4

Je suis un débutant absolu en C++. Littéralement. Ça fait juste une semaine. Aujourd'hui, j'écrivais un programme pour tester combien d'itérations sont nécessaires pour faire un certain nombre palindromique. Voici le code:std :: _ throw_out_of_range se produit de nulle part

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

/* This program calculates the steps needed 
    to make a certain number palindromic. 
    It is designed to output the values for 
    numbers 1 to 1000 
*/ 
using namespace std; 

class number 
{ 
public: 
    string value; 
    void reverse(); 
}; 

void number::reverse() 
{ 
    std::reverse(value.begin(),value.end()); 
} 

void palindrome(number num) 
{ 
    string n=num.value; 
    number reversenum, numsum, numsumreverse; 
    reversenum=num; 
    reversenum.reverse(); 
    numsum.value=num.value; 
    numsumreverse.value=numsum.value; 
    numsumreverse.reverse(); 
    int i=0; 
    while (numsum.value.compare(numsumreverse.value) !=0) 
    { 
     reversenum=num; 
     reversenum.reverse(); 
     numsum.value=to_string(stoll(num.value,0,10)+stoll(reversenum.value,0,10)); 
     numsumreverse.value=numsum.value; 
     numsumreverse.reverse(); 
     num.value=numsum.value; 
     i++; 
    } 
    cout << "The number " << n << " becomes palindromic after " << i << " steps : " << num.value << endl; 
} 

int main() 
{ 
    number temp; 
    int i; 
    for (i=1; i<1001; i++) 
    { 
     temp.value=to_string(i); 
     palindrome(temp); 
    } 
    return 0; 
} 

Il passe en douceur pour les nombres JUSQU'A Mais 195., en cas de 196 je reçois une erreur. Il dit:

Mettre fin à appelé après avoir jeté une instance de 'std :: out_of_range' ce(): stoll

Je ne peux pas faire ce qu'il faut faire. J'ai essayé à partir de 196 mais l'erreur a persisté. Toute aide est la bienvenue. :)

MISE À JOUR: Cette fois, j'ai essayé de le faire en utilisant la bibliothèque ttmath. Mais arghs! Il s'arrête de nouveau à 195 et ne signale même pas une erreur! Je pourrais faire quelque chose d'idiot. Tous les commentaires seraient appréciés. Voici le code mis à jour:

#include <iostream> 
#include <string> 
#include <algorithm> 
#include <ttmath/ttmath.h> 

/* This program calculates the steps needed 
    to make a certain number palindromic. 
    It is designed to output the values for 
    numbers 1 to 1000 
*/ 
using namespace std; 

class number 
{ 
public: 
    string value; 
    void reverse(); 
}; 

void number::reverse() 
{ 
    std::reverse(value.begin(),value.end()); 
} 

template <typename NumTy> 
string String(const NumTy& Num) 
{ 
    stringstream StrStream; 
    StrStream << Num; 
    return (StrStream.str()); 
} 

void palindrome(number num) 
{ 
    string n=num.value; 
    number reversenum, numsum, numsumreverse; 
    reversenum=num; 
    reversenum.reverse(); 
    numsum.value=num.value; 
    numsumreverse.value=numsum.value; 
    numsumreverse.reverse(); 
    ttmath::UInt<100> tempsum, numint, reversenumint; 
    int i=0; 
    while (numsum.value.compare(numsumreverse.value) !=0) 
    { 
     reversenum=num; 
     reversenum.reverse(); 
     numint=num.value; 
     reversenumint=reversenum.value; 
     tempsum=numint+reversenumint; 
     numsum.value=String<ttmath::UInt<100> >(tempsum); 
     numsumreverse.value=numsum.value; 
     numsumreverse.reverse(); 
     num.value=numsum.value; 
     i++; 
    } 
    cout << "The number " << n << " becomes palindromic after " << i << " steps : " << num.value << endl; 
} 

int main() 
{ 
    number temp; 
    int i; 
    for (i=196; i<1001; i++) 
    { 
     temp.value=to_string(i); 
     palindrome(temp); 
    } 
    return 0; 
} 

MISE À JOUR: C'est résolu. Certaines recherches ont suggéré que 196 pourrait être un Lychrel Number. Et le résultat que je recevais après avoir impliqué la bibliothèque ttmath est juste rassurant que mon algorithme fonctionne. Je l'ai essayé pour tous les nombres jusqu'à 10000 et il a donné les résultats parfaits. Voici le code final:

#include <iostream> 
#include <string> 
#include <algorithm> 
#include <ttmath/ttmath.h> 
#include <limits> 

/* This program calculates the steps needed 
    to make a certain number palindromic. 
    It is designed to output the values for 
    numbers inside a desired range 
*/ 
using namespace std; 
string LychrelList; 
int LychrelCount=0; 

class number 
{ 
public: 
    string value; 
    void reverse(); 
}; 

void number::reverse() 
{ 
    std::reverse(value.begin(),value.end()); 
} 

template <typename NumTy> 
string String(const NumTy& Num) 
{ 
    stringstream StrStream; 
    StrStream << Num; 
    return (StrStream.str()); 
} 

void palindrome(number num) 
{ 
    string n=num.value; 
    number reversenum, numsum, numsumreverse; 
    reversenum=num; 
    reversenum.reverse(); 
    numsum.value=num.value; 
    numsumreverse.value=numsum.value; 
    numsumreverse.reverse(); 
    ttmath::UInt<100> tempsum, numint, reversenumint; 
    int i=0; 
    while ((numsum.value.compare(numsumreverse.value) !=0) && i<200) 
    { 
     reversenum=num; 
     reversenum.reverse(); 
     numint=num.value; 
     reversenumint=reversenum.value; 
     tempsum=numint+reversenumint; 
     numsum.value=String<ttmath::UInt<100> >(tempsum); 
     numsumreverse.value=numsum.value; 
     numsumreverse.reverse(); 
     num.value=numsum.value; 
     i++; 
    } 
    if (i<200) cout << "The number " << n << " becomes palindromic after " << i << " steps : " << num.value << endl; 
    else 
    { 
     cout << "A solution for " << n << " could not be found!!!" << endl; 
     LychrelList=LychrelList+n+" "; 
     LychrelCount++; 
    } 
} 

int main() 
{ 
    cout << "From where to start?" << endl << ">"; 
    int lbd,ubd; 
    cin >> lbd; 
    cout << endl << "And where to stop?" << endl <<">"; 
    cin >> ubd; 
    cout << endl; 
    number temp; 
    int i; 
    for (i=lbd; i<=ubd; i++) 
    { 
     temp.value=to_string(i); 
     palindrome(temp); 
    } 
    if (LychrelList.compare("") !=0) cout << "The possible Lychrel numbers found in the range are:" << endl << LychrelList << endl << "Total - " << LychrelCount; 
    cout << endl << endl << "Press ENTER to end the program..."; 
    cin.ignore(numeric_limits<streamsize>::max(), '\n'); 
    string s; 
    getline(cin,s); 
    cout << "Thanks for using!"; 
    return 0; 
} 

C'est une communauté vraiment géniale. Un merci spécial à Marco A. :)

UPDATE AGAIN: J'ai conçu ma propre fonction add() qui réduit la dépendance du programme aux bibliothèques externes. Il en résulte un plus petit exécutable et des performances plus rapides aussi. Voici le code:

#include <iostream> 
#include <string> 
#include <algorithm> 
#include <limits> 

/* This program calculates the steps needed 
    to make a certain number palindromic. 
    It is designed to output the values for 
    numbers inside a desired range 
*/ 
using namespace std; 
string LychrelList; 
int LychrelCount=0; 

string add(string sA, string sB) 
{ 
    int iTemp=0; 
    string sAns; 
    int k=sA.length()-sB.length(); 
    int i; 
    if (k>0){for (i=0;i<k;i++) {sB="0"+sB;}} 
    if (k<0) {for (i=0;i<-k;i++) {sA="0"+sA;}} 
    for (i=sA.length()-1;i>=0;i--) 
    { 
     iTemp+=sA[i]+sB[i]-96; 
     if (iTemp>9) 
     { 
      sAns=to_string(iTemp%10)+sAns; 
      iTemp/=10; 
     } 
     else 
     { 
      sAns=to_string(iTemp)+sAns; 
      iTemp=0; 
     } 
    } 
    if (iTemp>0) {sAns=to_string(iTemp)+sAns;} 
    return sAns; 
} 

void palindrome(string num) 
{ 
    string n=num; 
    string reversenum, numsum, numsumreverse; 
    numsum=num; 
    numsumreverse=numsum; 
    reverse(numsumreverse.begin(),numsumreverse.end()); 
    int i=0; 
    while ((numsum.compare(numsumreverse) !=0) && i<200) 
    { 
     reversenum=num; 
     reverse(reversenum.begin(),reversenum.end()); 
     numsum=add(num,reversenum); 
     numsumreverse=numsum; 
     reverse(numsumreverse.begin(),numsumreverse.end()); 
     num=numsum; 
     i++; 
    } 
    if (i<200) cout << "The number " << n << " becomes palindromic after " << i << " steps : " << num << endl; 
    else 
    { 
     cout << "A solution for " << n << " could not be found!!!" << endl; 
     LychrelList=LychrelList+n+" "; 
     LychrelCount++; 
    } 
} 

int main() 
{ 
    cout << "From where to start?" << endl << ">"; 
    int lbd,ubd; 
    cin >> lbd; 
    cout << endl << "And where to stop?" << endl <<">"; 
    cin >> ubd; 
    cout << endl; 
    string temp; 
    int i; 
    for (i=lbd; i<=ubd; i++) 
    { 
     temp=to_string(i); 
     palindrome(temp); 
    } 
    if (LychrelList.compare("") !=0) cout << "The possible Lychrel numbers found in the range are:" << endl << LychrelList << endl << "Total - " << LychrelCount; 
    cout << endl << endl << "Press ENTER to end the program..."; 
    cin.ignore(numeric_limits<streamsize>::max(), '\n'); 
    string s; 
    getline(cin,s); 
    cout <<endl << "Thanks for using!"; 
    return 0; 
} 

Vous m'avez beaucoup aidée à trouver mon chemin. Merci tout le monde. :)

+2

Je doute qu'il se produise de "nulle part". Avez-vous même envisagé de lire la documentation de 'stoll'? Cela aurait expliqué le problème tout de suite. –

Répondre

2

Vous débordelong long depuis les deux dernières valeurs valides de num.value et reversenum.value sont 7197630720180367016 et 6107630810270367917 qui, additionnés, se situent au-dessus de la taille maximale d'un long long (9223372036854775807 sur ma machine). Cela donne une valeur négative et gâcher votre prochain appel à stoll

std :: out_of_range est levée si la valeur convertie tomberait hors de portée du type de résultat ou si la fonction sous-jacente (std :: strtol ou std :: strtoll) définit errno à ERANGE.

(reference)

  • Si vous essayez d'obtenir le plus petit suivant palindrome, vous devez utiliser une autre approche comme celle I explained here.

Vous pouvez trouver un Live Example ici

  • Si vous préférez/doit poursuivre votre approche, vous devez soit faire l'ajout manuellement sur les chaînes ou utiliser une bibliothèque bigint (prendre à nouveau un coup d'oeil à here et modifier la fonction plusOne() à votre goût)
+0

Donc, devrais-je utiliser la variable UInt de ttmath à la place? – SinTan1729

+0

@SayantanSantra J'ai ajouté une explication complète au cas où vous essayeriez de trouver le palindrome le plus petit suivant avec un numéro d'entrée 'N', plus une solution de repli si vous préférez continuer votre approche. Si 'UInt' est synonyme de' entier non signé ', cela n'aiderait pas. Jetez un oeil à la [gamme de valeurs] (http://en.cppreference.com/w/cpp/language/types) ici. L'utilisation d'un «long unsigned long» pourrait vous aider à dépasser cette valeur, mais je suggère d'utiliser une approche différente, comme je l'ai expliqué à la place. –

+0

En fait, ce que j'essaie est de voir combien de pas sont nécessaires pour transformer un nombre en palindrome. Vous savez, il y a une conjecture que chaque nombre naturel peut être transformé en un palindrome en un nombre fini d'étapes. – SinTan1729

1

de http://www.cplusplus.com/reference/string/stoll/

Si la valeur lue est en dehors de la plage de valeurs représentables d'une longueur longue, une exception out_of_range est levée.

Le type de données ll ne peut pas gérer la longueur de chaîne. Mon débogueur me dit 196 ruptures sur la valeur std::stoll (__str=\"9605805010994805921-\", __idx=0x0, __base=10)

Le long long est trop petit.

Vous pouvez effectuer l'ajout sur les chaînes elles-mêmes, sans recourir à un type numérique.

+0

Donc, devrais-je utiliser la variable UInt de ttmath à la place? – SinTan1729