• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

terminate called after throwing an instance of 'std::out_of_range' what(): basic_string::substr

Object Storage Arubacloud
0 głosów
1,775 wizyt
pytanie zadane 1 stycznia 2021 w C i C++ przez nilam Nowicjusz (120 p.)

Witam, mam za zadanie napisać program podający wyniki operacji arytmetycznych dla dużych liczb całkowitych
dodatnich. Należy uwzględnić 4 podstawowe operacje: dodawanie (+), odejmowanie (-),
mnożenie (*) i dzielenie całkowite (/).
Pierwszy wiersz standardowego wejścia zawiera jedną liczbę całkowitą Z (1 ? Z ? 200)
określającą liczbę testów zdefiniowanych w kolejnych wierszach. Każdy test zajmuje jeden
wiersz standardowego wejścia i zawiera zapis jednego działania arytmetycznego, tzn. dwa
ciągi cyfr rozdzielone operatorem działania (bez dodatkowych spacji). Ciągi cyfr liczą nie
więcej niż 256 znaków.
Mam na razie taki kod i dziala dla dodawania, odejmowania i mnozenia, jednak nie w pętli, która jest potrzebna,żeby przeprowadzić wiele testów tak jakw poleceniu.
Kiedy jednak stosuję pętlę while wyświetla mi się taki komunikat "terminate called after throwing an instance of 'std::out_of_range' what(): basic_string::substr'

Wiem, że  w kodzie jest dużo niepotrzebnych 'cout' ułatwia mi to pisać kod, a po skończeniu je usuwam.

#include <iostream>
#include <string>

using namespace std;



string add(string a, string b)  // column addition
{
    int pa= a.length()-1;		//we find the position of the last digit in the strings a and b
    int pb= b.length()-1;

    string result="";           //empty string that will be the result

    int c=0;                    //'c' - carrying ,the digit that we will carry to the next column


    while (pa >=0 || pb >=0)     //the loop to successively add the digits of strings a and b
    {
        int r, ca, cb;
        if (pa>=0)              //we calculate the values of the digits
            ca= a[pa]-48;       //ASCII of 0 is 48, so to get an integer we have to substract 48
        else
            ca=0;

        if(pb>=0)
            cb= b[pb]-48;
        else
            cb=0;

        r= ca+cb+c;             //we calculate the sum of the digits remembering about the digit that we've carried from the last column

        result="0"+result;      // to the result string we add the result from the previous loop
        result[0]=48+r%10;      // we put the last digit of 'r' to the 0th index of the result

        c=r/10;                 //we calculate what digit will have to be carried to the next column

        pa--; pb--;             //we decrement the position of the last digit
    }
    if(c)                       //if c is 1 we add "1" at the beggining of the result
        result="1"+ result;
    return result;
}
string substract(string a, string b) //colun substraction
{
   int pa= a.length()-1;
    int pb= b.length()-1;
    string result="";
    int c=0;
    int A, B;
    if(a.length()<b.length())
    {
        A=0;
        B=1;
    }
    else if (a.length()==b.length())
    {
        int i=0;
        while(i<=a.length())
        {
            if(a[i]-48<b[i]-48)
            {
                A=0;
                B=1;
                break;
            }
            else if(a[i]-48>b[i]-48)
            {
                A=1;
                B=0;
                break;
            }
            else if(a[i]-48==b[i]-48)
                A=1;
                B=1;
                i++;
        }
    }
    else
    {
        A=1;
        B=0;
    }
    cout<<A<<endl<<B<<endl;
    if(A>B)
    {
        while (pa >=0 || pb >=0)
        {
            int r, ca, cb;
            if (pa>=0)
                ca= a[pa]-48-c;
            else
                ca=0;

            if(pb>=0)
                cb= b[pb]-48;
            else
                cb=0;

            if (ca<cb)
            {
                ca= ca+10;
                c=1;
                r=ca-cb;
            }
            else
            {
                r=ca-cb;
                c=0;
            }
            result="0"+result;
            result[0]=48+r%10;


            pa--; pb--;
        }
    }
    else if(B>A)
    {
        while (pa >=0 || pb >=0)
        {
            int r, ca, cb;
            if (pa>=0)
                ca= a[pa]-48;
            else
                ca=0;

            if(pb>=0)
                cb= b[pb]-48-c;
            else
                cb=0;

            if (cb<ca)
            {
                cb= cb+10;
                c=1;
                r=cb-ca;
            }
            else
            {
                r=cb-ca;
                c=0;
            }
            result="0"+result;
            result[0]=48+r%10;

            pa--; pb--;
        }
    }
    else if (A=B)
        return 0;
    for(int i=0; i<=result.length();)
    {
        if(result[i]=='0')
            result.erase(i,1);
        else
            break;
    }
    if(B>A)
        result="-"+result;
    return result;
}
string multiply(string a, string b) {
    if(a[0]=='0'||b[0]=='0') return "0";
    int n1(a.size()), n2(b.size()), n(n1+n2);
    cout<<"n1 "<<n1<<endl;
    cout<<"n2 "<<n2<<endl;
    cout<<"n "<<n<<endl;
    int r[n];
    for (int x=0; x<=n; x++)
    {
        r[x]=0;
    }
    cout<<"r "<<r[n-1]<<endl;
    string      s(n,'0');
    cout<<"s "<<s<<endl;
    for(size_t i=0;i<n1;++i){
        for(int j=0;j<n2;++j){
            {
            int ca=a[i]-48;
            int cb=b[j]-48;
            r[i+j+1]+=(ca*cb);
            cout<<"r[i+j+1] "<<r[i+j+1]<<endl;
            cout<<"i+j+1 "<<i+j+1<<endl;
            cout<<"j "<<j<<endl;
            cout<<"i "<<i<<endl;
            cout<<"a[i] "<<a[i]<<endl;
            cout<<"b[j] "<<b[j]<<endl;
            }
        }
    }
    for(int i=n-1;i>0;--i){
        if(r[i]>9)  r[i-1]+=r[i]/10;
        cout<<"i "<<i<<endl;
        cout<<"r[i-1] "<<r[i-1]<<endl;
        cout<<"r[i] "<<(r[i]%10)+48<<endl;
        s[i]  = (r[i]%10)+48;
        cout<<"s[i] "<<s[i]<<endl;
    }
    s[0]+=r[0]+48;
    cout<<"r "<<r[0]<<endl;
    cout<<"s "<<s<<" "<<s[0]<<endl;
    string result;
    result=s;
    cout<<result<<endl;
    //cout<<s.begin()+1<<" "<<s.end()<<endl;
    if(s[0]=='0')
    {
        result=s.substr(1,s.length());
        cout<<result;
    }
    return result;
}
int main()
{   int n;
    string s, a, b;
    cin>>n;
    while(n)
    {
        int A;
        getline(cin, s);
        if(s.find('+')!=string::npos)
        {
            A=s.find('+');
            cout<<A;
        }
        else if(s.find('-')!=string::npos)
        {
            A=s.find('-');
            cout<<A;
        }
        else if(s.find('*')!=string::npos)
        {
            A=s.find('*');
            cout<<A;
        }
        else if(s.find('/')!=string::npos)
        {
            A=s.find('/');
            cout<<A;
        }
        a=s.substr(0,A);

        int B=s.length();
        b=s.substr(A+1,B);
        cout<<a<<endl;
        cout<<b<<endl;
        if(s.find('+')!=string::npos)
        {
            cout<<add(a,b);
        }
        if(s.find('-')!=string::npos)
        {
            cout<<substract(a,b);
        }
        if(s.find('*')!=string::npos)
        {
            cout<<multiply(a,b);

        }
        if(s.find('/')!=string::npos)
        {
            cout<<"/"<<endl;
        }
    }
    return 0;
}


Bede wdziczny za pomoc jak rozwiazac ten problem.

1 odpowiedź

+1 głos
odpowiedź 1 stycznia 2021 przez NewEraOfPeace Gaduła (4,790 p.)
Linijki 244 i 245.
Pobierasz długość stringa, a następnie próbujesz zdobyć substring od A+1, dokładnie b.length() znaków. Zajrzyj tutaj:
https://en.cppreference.com/w/cpp/string/basic_string/substr

pobaw się trochę tą metodą i zobacz jak działa.

 

.. poza tym polecam lepiej formatować kod i nazywać zmienne w sensowny sposób. Przez dobre 5 minut zastanawiałem się, czy opłaca mi się to w ogóle kopiować do edytora, na szczęście błąd był bliżej, niż myślałem.

PS nie sprawdzałem innych błędów, ale patrząc na szybko w linijce 147, w ifie masz przypisanie, zamiast porównania
komentarz 1 stycznia 2021 przez j23 Mędrzec (194,920 p.)

Dorzucę jeszcze pętlę while z linii 59, która wychodzi poza zakres stringa.

komentarz 2 stycznia 2021 przez nilam Nowicjusz (120 p.)

@NewEraOfPeace, 

Bardzo dziękuję za wskazanie błędów, poprawiłem już ten z ifem, ale nadal nie potrafię otrzymać substringa b, rozumiem, że rozmiar podawany przeze mnie był za duży, ale kiedy podaję mniejszy, wciąż pokazuje się mi błąd.

i dziękuję za radę, na przyszłość będę lepiej formatować i nazywać zmienne (do tej pory pisałem tylko krótkie programy, do których używanie liter a czy b wystarczało)

komentarz 2 stycznia 2021 przez NewEraOfPeace Gaduła (4,790 p.)
Pobaw się z tą funkcją, pobaw się z jej argumentami, losowymi stringami, zobacz jak działa. Zwizualizuj sobie jej działanie na kartce, może w programie, może w głowie.
komentarz 3 stycznia 2021 przez nilam Nowicjusz (120 p.)
Dziękuję za pomoc, funkcja już działa.

Podobne pytania

–1 głos
0 odpowiedzi 224 wizyt
0 głosów
0 odpowiedzi 1,977 wizyt
pytanie zadane 28 października 2018 w C# przez DreaM Użytkownik (840 p.)

92,584 zapytań

141,434 odpowiedzi

319,671 komentarzy

61,968 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...