Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Program wyszukujący niepowtarzające się liczby z danego zbioru

Ostatnio zmodyfikowano 2017-01-01 19:33
Autor Wiadomość
Jekon
Temat założony przez niniejszego użytkownika
[C++] Program wyszukujący niepowtarzające się liczby z danego zbioru
» 2016-12-29 19:58:39
Witam. Niedawno napisałem program, którego zadaniem miało być wypisanie niepowtarzających się liczb ze zbioru 10 podanych przez użytkownika. Po pomyślnym skompilowaniu, program po zatwierdzeniu ostatniej (10.) zmiennej zawiesza się - komunikat Windowsa "Program x.exe przestał działać". Nie wiem co jest tego przyczyną. Uprzejmie proszę o pomoc w zlikwidowaniu tego błędu oraz o ocenę mojego kodu źródłowego - błąd nie pozwala mi sprawdzić czy program wykonuje swoje zadanie poprawnie. Dodam, że dopiero zaczynam swoją przygodę z C++. Z góry dziękuję! :)

C/C++
#include <iostream>
#include <windows.h>

using namespace std;
int main()
{
    system( "chcp 1250" );
    system( "cls" );
   
    int x[ 9 ] = { 0 };
    bool z[ 9 ] = { 0 };
   
    cout << "Podaj dowolne wartości: " << endl << endl;
    for( int i = 0; i < 10; i++ )
    {
        cout << i + 1 << ". = ";
        cin >> x[ i ];
    }
   
    system( "cls" );
    cout << "Oto liczby które wystąpiły tylko raz: " << endl << endl;
   
    for( int i = 0; i < 9; i++ )
    {
        for( int j = i + 1; i < 9 && z[ i ] == 0; j++ )
        {
            if( x[ i ] == x[ j ] )
            {
                z[ i ] = 1;
                z[ j ] = 1;
            }
        }
        if( z[ i ] == 0 )
        {
            cout << x[ i ] << endl;
        }
    }
   
    cin.get();
    cin.get();
    return 0;
}
P-155658
carlosmay
» 2016-12-29 20:18:09
C/C++
for( int i = 0; i < 10; i++ )
{
    cout << i + 1 << ". = ";
    cin >> x[ i ];
}
Wyjście poza zakres tablicy.
P-155659
Jekon
Temat założony przez niniejszego użytkownika
Tablica
» 2016-12-30 14:18:20
Nie rozumiem. Jest to tablica 10-elementowa kończąca się "9". A 9 spełnia warunek "<10". Dopiero 10 kończy pętle i nie wczytuje "10." nieistniejącej tablicy.
P-155693
latajacaryba
» 2016-12-30 14:26:45
C/C++
int x[ 9 ] = { 0 }; // tablica ma 9 elementow

C/C++
for( int i = 0; i < 10; i++ )
{
    cout << i + 1 << ". = ";
    cin >> x[ i ];
}
petla powtarza sie 10 razy! dla i równego:
0
1
2
3
4
5
6
7
8
9

Co daje nam 10 powtórzeń

zrób tablicę
int tab[ 10 ]

Edit:
Nie rozumiem. Jest to tablica 10-elementowa kończąca się "9". A 9 spełnia warunek "<10". Dopiero 10 kończy pętle i nie wczytuje "10." nieistniejącej tablicy.
Nie. w nawiasach kwadratowych [] określasz wielkość tablicy, jej rozmiar, a nie ostatni element. To znaczy, że jeśli napiszesz int tab[3] to jest to tablica int o trzech elementach - tab[0], tab[1] i tab[2]
P-155694
Jekon
Temat założony przez niniejszego użytkownika
Brak efektu
» 2016-12-30 16:17:20
latajacaryba wielkie dzięki za wytłumaczenie! Teraz już rozumiem :P

Jednak mimo poprawy, program nadal po zatwierdzeniu ostatniej zmiennej zacina się - "Program x.exe przestał działać". W czym w takim razie leży problem? Domyślam się że gdzieś w pętli, porównującej te liczby, ale gdzie konkretnie?

Postanowiłem też lekko zmodyfikować kod, aby program nie musiał sprawdzać czy dana liczba się powtarza, jeżeli powtórzyła się już wcześniej - dodałem opcję warunkową, która sprawdza przed wewnętrzną pętlą czy wartość logiczna odpowiednika danej zmiennej jest prawdziwa czy też nie.

C/C++
#include <iostream>
#include <windows.h>

using namespace std;
int main()
{
    system( "chcp 1250" );
    system( "cls" );
   
    int x[ 10 ] = { 0 };
    bool z[ 10 ] = { 0 };
   
    cout << "Podaj dowolne wartości: " << endl << endl;
    for( int i = 0; i < 10; i++ )
    {
        cout << i + 1 << ". = ";
        cin >> x[ i ];
    }
   
    system( "cls" );
    cout << "Oto liczby które wystąpiły tylko raz: " << endl << endl;
   
    for( int i = 0; i < 10; i++ )
    {
        if( z[ i ] == 0 )
        {
            for( int j = i + 1; i < 10 && z[ i ] == 0; j++ )
            {
                if( x[ i ] == x[ j ] )
                {
                    z[ i ] = 1;
                    z[ j ] = 1;
                }
            }
        }
        if( z[ i ] == 0 )
        {
            cout << x[ i ] << endl;
        }
    }
   
    cin.get();
    cin.get();
    return 0;
}
Jednak i to nie przyniosło żadnego efektu...

Może jest inny, mniej skomplikowany sposób na rozwiązanie tego problemu w C++?
P-155701
michal11
» 2016-12-30 16:36:26
Najprościej będzie skorzystać ze zbioru http://www.cplusplus.com​/reference/set/set/?kw=set.

Program napisany na szybko:
C/C++
#include <iostream>
#include <algorithm>
#include <set>
#include <iterator>

int main()
{
    int n;
    std::cin >> n;
   
    std::set < int > IntSet;
   
    std::copy_n( std::istream_iterator < int >( std::cin ), n, std::inserter( IntSet, IntSet.end() ) );
   
    std::copy( IntSet.begin(), IntSet.end(), std::ostream_iterator < int >( std::cout, ", " ) );
   
    return 0;
}

jeżeli jeszcze nie znasz stlowych algorytmów to można tak zapisać powyższy program
C/C++
int n;
std::cin >> n;

std::set < int > IntSet;
int num;
for( int i = 0; i < n; ++i )
{
    std::cin >> num;
    IntSet.insert( num );
}

for( const int & el: IntSet )
{
    std::cout << el << ", ";
}

P-155705
carlosmay
» 2016-12-30 16:39:11
C/C++
#include <iostream>
#include <array>
#include <algorithm>

template < class C >
const bool is_single_num( const C & coll, int checked )
{
    return { std::count( coll.cbegin(), coll.cend(), checked ) == 1 ? true
            : false };
}

int main()
{
    std::array < int, 10 > nums { 1, 2, 3, 5, 4, 4, 2, 8, 6, 1 };
    for( std::size_t i { }; i < nums.size(); ++i ) {
        if( is_single_num( nums, nums[ i ] ) ) {
            std::cout << "Liczba " << nums[ i ] << " pajawia sie w tablicy tylko raz\n";
        }
    }
}
P-155706
latajacaryba
» 2016-12-30 17:34:32
Na wstępie zaznaczę, że kończyłem pisanie kiedy przez prypadek kliknąłem klawisz powrotu na poprzednią stronę przy klawiszach strzałek. Co za... je tam umieścił ;-;
Oraz zauwazylem dopiero teraz. Tam gdzie masz samo x lub z bez nawiasow kwadratowych - tam ma byc zmienna 'i' w nawiasach kwadratowych tylko cos dziwnie mi tekst formatuje i nie widac tego :/ czyli x czytaj jako x[.i]
Ok, tu jest program bez funkcji bibliotecznych:
C/C++
#include <iostream>
#include <windows.h>

using namespace std;
int main()
{
    system( "chcp 1250" );
    system( "cls" );
   
    int x[ 10 ] = { 0 };
    bool z[ 10 ] = { 0 };
    cout << "Podaj dowolne wartości: " << endl << endl;
    for( int i = 0; i < 10; i++ )
    {
        cout << i + 1 << ". = ";
        cin >> x[ i ];
    }
   
    system( "cls" );
    cout << "Oto liczby ktore wystapily tylko raz: " << endl << endl;
   
    for( int i = 0; i < 10; i++ )
    {
        for( int l = 0; l < 10; l++ )
        {
            if( l != i && x[ i ] == x[ l ] ) // 1
            {
                z[ i ] = true; //2
                break; //3
            }
        }
        if( z[ i ] == false ) // 4
             cout << "bez powtorzenia: " << x[ i ] << endl;
       
    }
    cin.get();
    cin.get();
    return 0;
}

1. pierwszy warunek if'a to i ma być nie równe l. dlaczego? spójrz, jak wykonuje się pętla:
i = 0, l = 0.
i = 0, l = 1
i = 0, l = 2
(...)
i = 0, l = 9
i = 1, l = 0
i = 1, l = 1
Czyli zawsze w końcu l będzie równe i. Co to znaczy dla nas? Spójrz:
Drugim warunkiem jest: jeśli x == x[l]
Czyli jeśli liczba w elemencie x jest równa liczbie w indeksie x[l].
Chwila! ale l zawsze w końcu będzie równe i. No właśnie. Po to jest pierwszy warunek. Jeśli l jest równe i to nie, instrukcje w ifie się nie wykonają! Bo skoro i = l, to x = x[l], czyli porównujemy liczby w tym samym indeksie! To tak jakbysmy napisali x == x. Zawsze więc, prędzej czy później tak by się stało. Tak więc warunek l != i chroni nas przed takim porównaniem. przykład: użytkownik podał liczby: 1,2,3,4,5,6,7,8,9,0.
If sprawdza:
i = 0, l = 0 czy x == x[l]? tak, więc wykonuje ciało if'a, 1 równa się 1.
A dziNa wstępie zaznaczę, że kończyłem pisanie kiedy przez prypadek kliknąłem klawisz powrotu na poprzednią stronę przy klawiszach strzałek. Co za... je tam umieścił ;-;
Ok, tu jest program bez funkcji bibliotecznych:
C/C++
#include <iostream>
#include <windows.h>

using namespace std;
int main()
{
    system( "chcp 1250" );
    system( "cls" );
   
    int x[ 10 ] = { 0 };
    bool z[ 10 ] = { 0 };
    cout << "Podaj dowolne wartości: " << endl << endl;
    for( int i = 0; i < 10; i++ )
    {
        cout << i + 1 << ". = ";
        cin >> x[ i ];
    }
   
    system( "cls" );
    cout << "Oto liczby ktore wystapily tylko raz: " << endl << endl;
   
    for( int i = 0; i < 10; i++ )
    {
        for( int l = 0; l < 10; l++ )
        {
            if( l != i && x[ i ] == x[ l ] ) // 1
            {
                z[ i ] = true; //2
                break; //3
            }
        }
        if( z[ i ] == false ) // 4
             cout << "bez powtorzenia: " << x[ i ] << endl;
       
    }
    cin.get();
    cin.get();
    return 0;
}

1. pierwszy warunek if'a to i ma być nie równe l. dlaczego? spójrz, jak wykonuje się pętla:
i = 0, l = 0.
i = 0, l = 1
i = 0, l = 2
(...)
i = 0, l = 9
i = 1, l = 0
i = 1, l = 1
Czyli zawsze w końcu l będzie równe i. Co to znaczy dla nas? Spójrz:
Drugim warunkiem jest: jeśli x == x[l]
Czyli jeśli liczba w elemencie x jest równa liczbie w indeksie x[l].
Chwila! ale l zawsze w końcu będzie równe i. No właśnie. Po to jest pierwszy warunek. Jeśli l jest równe i to nie, instrukcje w ifie się nie wykonają! Bo skoro i = l, to x = x[l], to tak jakbyśmy napisali x == x.
przykład - użytkownik podał liczby: 1,2,3,4,5,6,7,8,9,0
program jest w pętlach,
i = 0, l = 0 i teraz ma tego naszego if'a. Czy x == x[l]? No tak! 1 równa się 1 (bo liczba 1 jest pod x[0] )
Przed tym chroni nas właśnie nasz pierwszy warunek. tak działa z naszym zabezpieczniem:
i = 0, l = 0, to zobaczmy, x jest równe x[l], ale jest warunek, że i nie może równać się l. W takim razie nie wykonujemy! pętla się powtarza, i teraz
i = 0, l = 1, i teraz takie porównanie ma sens. porównujemy liczbę x do x[l], czyli liczbę 1 do 2.

2 i 3.
Jesli warunki były prawdziwe, to z = true;
Czyli odpowiadający indeksowi x indeks z przybiera wartość true. następnie przerywamy pętle dzięki
break;
4. Jeśli z == false - czyli było nie ruszane przez naszego if'a, to wyswietl liczbe x.

Czegoś nie zrozumiałeś? - pisz :)
P-155708
« 1 » 2 3
  Strona 1 z 3 Następna strona