2009-11-19 21 views
1

Je travaille sur un programme pour Project Euler pour ajouter tous les chiffres de 2^1000. Jusqu'ici j'ai été capable de suivre les défauts de segmentation de programme quand il atteint environ 5 chiffres et essaye d'en pousser un sur le vecteur à la ligne 61 dans la fonction carry().Causer push_back dans le vecteur <int> à la faute de segmentation sur ce qui semble être opération simple

#include <iostream> 
#include <vector> 
#include <string> 
using namespace std; 

class MegaNumber 
{ 
     vector<int> data; //carries an array of numbers under ten, would be char but for simplicity's sake 
     void multiplyAssign(int operand, int index); //the recursive function called by the *= operator 
     void carry(int index);//if one of the data entries becomes more than ten call this function 
    public: 
     void printNumber(); //does what it says on the can 
     void operator*=(MegaNumber operand); 
     void operator*=(int operand); 
     void operator+=(int operand); 
     MegaNumber(string); 
     unsigned long int AddAllDigits();//returns the value of all of the digits summed 
}; 

MegaNumber::MegaNumber(string operand) 
{ 
    for(int i= operand.size()-1; i>=0;i--) //run it into the memory smallest digit first 
    { 
     data.push_back(operand[i]-48); //converts a text char to an int 
    } 
} 

void MegaNumber::printNumber() 
{ 
    int temp = data.size(); 
    for(unsigned int i=(temp); i>0;--i) 
    { 
    cout << (int)data[i-1]; 
    } 
} 

void MegaNumber::operator*=(int operand) 
{ 
    if(operand > 9) 
    { 
     cout << "function does not yet deal with large ints than 9"; 
    } 
    else multiplyAssign(operand, 0); 
} 

void MegaNumber::multiplyAssign(int operand, int index) 
{ 
    data[index] *=operand; 
    if(index<data.size()) multiplyAssign(operand, index+1); 
    if(data[index] > 9) carry(index); 
} 

void MegaNumber::carry(int index) 
{ 

    int temp = (data[index]/10); //calculate the amount to carry 
    if(data.size()==index+1) 
    { 
    data.push_back(temp);//if there is no upper digit push it onto the stack 
    } 
    else 
    { 
     data[index+1]+=temp; //else add it to the next digit 

     if(data[index+1]>9) carry(index+1); //rinse and repeat 
    } 
    data[index]-=temp*10; //remove what's been carried 
} 

unsigned long int MegaNumber::AddAllDigits() //does what it says on the can 
{ 
    unsigned long int Dagger = 0; 
    for(int i=0; i<data.size();i++) Dagger+=data[i]; 
    return Dagger; 
} 

int main() 
{ 
    MegaNumber A("2"); 
    A.printNumber(); 
    cout << "\n"; 
    for(unsigned int i=0; i<20; i++) A*=2; 
    A.printNumber(); 
    cout << "\n"; 
    cout << A.AddAllDigits() << "\n"; 
    cout << "Hello world!" << endl; 
    return 0; 
} 

Ce qui peut être à l'origine de cela?

+0

Quelle est l'idée d'utiliser la récursivité dans 'multiplyAssign'. Cela pourrait provoquer un débordement de pile pour un grand nombre de tableaux. – Elalfer

+0

J'ai récemment été introduit à la récursivité et, pour être tout à fait honnête, cela semblait être une bonne idée à l'époque. J'apprécie la contribution sur ma technique, c'est quelque chose que j'essaie d'affiner. – Sparky

Répondre

2
void MegaNumber::multiplyAssign(int operand, int index) 
{ 
    data[index] *=operand; 
    if(index<data.size()) multiplyAssign(operand, index+1); 
    if(data[index] > 9) carry(index); 
} 

index est 0 base, alors que data.size() est 1 basé pour ainsi dire, ce qui signifie data.size() renvoie le numéro 1 plus grand que le plus grand valide index . semble donc comme vous l'intention était

if(index < data.size() - 1) multiplyAssign(operand, index+1); 

Ensuite, il fonctionne.
P.S. briser votre code en ligne, celui qui doit maintenir votre code vous remercie:

if (index < data.size() - 1) 
{ 
    multiplyAssign(operand, index + 1); 
} 
+0

C'est ce que je n'ai pas compris, merci beaucoup. – Sparky

+0

Bien que certaines conventions indiquent que vous utilisez plusieurs lignes, vous avez besoin d'accolades. Je trouve cela raisonnable, pas beaucoup de travail, et plus proche de ce que ceux qui apprennent la langue s'attendent. –

+0

J'ai tendance à être d'accord avec ces conventions et généralement bouclé. Le message est édité. Merci. – BostonLogan

3

Vous utilisez des données [index] avant de vérifier si elle est un index valide, en multiplyAssign:

data[index] *= operand; 
if(index<data.size()) multiplyAssign(operand, index+1); 

utiliser également '0' au lieu de 48. C'est plus facile, plus clair et moins sujet aux bogues.

+2

S'il ne s'agit pas d'une partie critique de votre code, pensez à utiliser le membre 'at' de' std :: vector'' à la place de 'operator []'; il fournit des bornes-vérification et vous aidera à trouver ce genre d'erreur plus rapidement. –

+0

Un bon conseil chaque fois que vous n'avez pas vérifié explicitement l'index immédiatement avant; changez-le plus tard si c'est un goulot d'étranglement. –

+0

Bon conseil, merci. – Sparky

1

Je pense que le problème pourrait être ici: data[index+1]+=temp;

Cet élément ne peut pas être exister si index eq paramètre. à la taille de data.

Alors, mes recommandations:

  • Utilisez itérateurs pour accéder std::vector
  • conditions Vérifiez lié si vous n'utilisez itérateurs