Zadanie SPOJ - Współliniowość punktów - błąd SIGABRT

0

Cześć wszystkim, chciałem wykonać to zadanie ze SPOJ'a: https://pl.spoj.com/problems/JWSPLIN/
Testując kod samodzielnie nie wyłapałem żadnych błędów, ale SPOJ wyrzuca mi błąd SIGABRT, którego zupełnie nie rozumiem i nie wiem w czym jest problem. Oto mój kod:

#include <iostream>

using namespace std;

int main()
{
    int testy;
    cin >> testy;
    for (int i=0; i<testy; i++)
    {
        float x[100][3];
        float y[100][3];
        for (int j=1; j<=3; j++)
        {
            //cout << i+1 << " Podaj x nr " << j << " : ";
            cin >> x[i+1][j];
            //cout << i+1 << " Podaj y nr " << j << " : ";
            cin >> y[i+1][j];

        }
        if ((x[i+1][1]==x[i+1][2] && x[i+1][2]==x[i+1][3]) || (y[i+1][1]==y[i+1][2] && y[i+1][2]==y[i+1][3])) //sprawdzenie czy punkty nie leza w jednej linii pionowo lub poziomo
        {
            cout << "TAK" << endl;

        }
        else
        {
            float a;
            float b;
            float sprawdzenie;
            a = (y[i+1][2]-y[i+1][1])/(x[i+1][2]-x[i+1][1]); //obliczenie wspolczynnika a w rownaniu liniowym na podstawie 2 pierwszych punktow
            b = y[i+1][1] - (a*x[i+1][1]); //obliczenie wspolczynnika b w rownaniu liniowym
            sprawdzenie = a*x[i+1][3] + b; //obliczenie wartosci y dla wspolrzednej x trzeciego punktu
            if (sprawdzenie==y[i+1][3]) //sprawdzenie czy trzeci punkt lezy na jednej linii wraz z pierwszym i drugim punktem
            {
                cout << "TAK" << endl;

            }
            else
            {
                cout << "NIE" << endl;

            }

        }

    }

    return 0;
}

3

"Cholero nie dziel przez zero." - pamiętasz?
(Ax-Cx)*(By-Cy)-(Ay-Cy)*(Bx-Cx)==0

https://en.wikipedia.org/wiki/Triangle rozdział "Using coordinates"

0

Wielkie dzięki za pomoc. Akurat pamiętałem o tej zasadzie przy innym wzorze, ale tu zupełnie ją pominąłem. Jesteś w stanie odpowiedzieć mi na pytanie dlaczego system wciąż wyrzuca mi ten błąd SIGABRT, nawet jeśli wyeliminuję ifem sytuację, w której 0 występuje w mianowniku?
Nie mogę w żadnym programie doprowadzić do sytuacji, w której w mianowniku będzie jakaś zmienna? Czy może jakiś problem jest z ifem i można to zrobić np. z użyciem instrukcji switch?

Wiem, że już podałeś mi prosty i jasny sposób rozwiązania zadania, ale po prostu jestem ciekaw jak to dokładnie działa.

#include <iostream>

using namespace std;

int main()
{
    int testy;
    cin >> testy;
    for (int i=0; i<testy; i++)
    {
        float x[100][3];
        float y[100][3];
        for (int j=1; j<=3; j++)
        {
            //cout << i+1 << " Podaj x nr " << j << " : ";
            cin >> x[i+1][j];
            //cout << i+1 << " Podaj y nr " << j << " : ";
            cin >> y[i+1][j];

        }
        if ((x[i+1][1]==x[i+1][2] && x[i+1][2]==x[i+1][3]) || (y[i+1][1]==y[i+1][2] && y[i+1][2]==y[i+1][3])) //sprawdzenie czy punkty nie leza w jednej linii pionowo lub poziomo
        {
            cout << "TAK" << endl;

        }
        else
        {
            float a;
            float b;
            float sprawdzenie;
            if (x[i+1][2]-x[i+1][1]==0)
            {
                cout <<"NIE"<<endl;
            }
            else
            {
                a = (y[i+1][2]-y[i+1][1])/(x[i+1][2]-x[i+1][1]); //obliczenie wspolczynnika a w rownaniu liniowym na podstawie 2 pierwszych punktow
                b = y[i+1][1] - (a*x[i+1][1]); //obliczenie wspolczynnika b w rownaniu liniowym
                sprawdzenie = a*x[i+1][3] + b; //obliczenie wartosci y dla wspolrzednej x trzeciego punktu
                if (sprawdzenie==y[i+1][3]) //sprawdzenie czy trzeci punkt lezy na jednej linii wraz z pierwszym i drugim punktem
                {
                    cout << "TAK" << endl;

                }
                else
                {
                    cout << "NIE" << endl;

                }


            }


        }

    }

    return 0;
}

3
  1. Wywal i napisz od nowa.
  2. Powtarzaj punkt pierwszy dopóki: w kodzie jest dzielenie, w kodzie jest tablica, kod zawiera więcej niż 15 wierszy.
3

Dziel na funkcje, będzie łatwiej i czytelniej: https://godbolt.org/z/o1b6jT6GE

0

Dzięki za pomoc i wskazówki

1

Ja tam wolę prostsze rozwiązania:

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
	int T;
	for(cin>>T;T--;)
	{
		double ax,ay,bx,by,cx,cy;
		cin>>ax>>ay>>bx>>by>>cx>>cy;
		cout<<(fabs((ax-cx)*(by-cy)-(ay-cy)*(bx-cx))<1E-7?"TAK":"NIE")<<endl;
	}
    return 0;
}

W przypadku jeżeli współrzędne typu całkowitego:

#include <iostream>
using namespace std;

int main()
{
    int T,ax,ay,bx,by,cx,cy;
    for(cin>>T;T--;cout<<((ax-cx)*(by-cy)-(ay-cy)*(bx-cx)?"NIE":"TAK")<<endl) cin>>ax>>ay>>bx>>by>>cx>>cy;
    return 0;
}
0

O, chyba nigdy bym nie wpadł na to, żeby w taki genialny sposób wpisać parametry do pętli for (w sensie to co w nawiasie, nie wiem czy dobrze to nazwałem). Chwilę mi zajęło ogarnięcie jak to dokładnie działa :D
Mi to wczoraj ostatecznie wyszło tak:

#include <iostream>

using namespace std;

int main()
{
    int testy;
    cin >> testy;
    for (int i=0; i<testy; i++)
    {
        int x1, x2, x3, y1, y2, y3;
        cin >> x1 >> y1 >> x2 >> y2 >> x3 >> y3;
        if ((x1-x3)*(y2-y3)-(y1-y3)*(x2-x3)==0)
        {
            cout << "TAK" << endl;
        }
        else cout << "NIE"<< endl;
    }
    return 0;
}

I już nie miałem pomysłów jak to można skrócić.

0

Czy na pewno masz w zadaniu int'y?
Bo jak int'y to 9 wierszy wystarczy. :D

0

Jest jakiś sposób, żeby nauczyć się tak sprawnie pisać pogramy? Powinienem skorzystać z jakiejś strony czy innych źródeł? Czy sama praktyka i robienie zadań/ pisanie programów wystarczy? Wiedzę o c++ czerpię głównie z Internetu.

1

Robienie zadań oraz koniecznie porównanie z innymi wykonawcami.

1

Jeśli się do czegoś porównywać, to trzeba pamiętać, że internet dobrze wypełnia prawo Sturgeon'a:

ninety percent of everything is crap.
nothing is always absolutely so

więc trzeba znaleźć źródło godne zaufania.

0
cin >> x[i+1][j];

Podczas gdy i jest z przedziału od 0 do 99, a j jest z zakresu od 1 do 3. Czyli robisz tutaj potencjalnie zapis do miejsca do którego nie masz prawa.
To co możesz robić tutaj, to odwołanie się do indeksów x[i][j], dla 0 <= i <= 99 oraz 0 <= j <= 2.

Abort sie pojawia, zapewne z tego powodu co opisane tutaj:
https://stackoverflow.com/questions/1345670/stack-smashing-detected#1347464

1 użytkowników online, w tym zalogowanych: 0, gości: 1