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

Jak zwrócić tablicę struktur / C++ ?

Ostatnio zmodyfikowano 2019-05-03 14:34
Autor Wiadomość
K1cek
Temat założony przez niniejszego użytkownika
Jak zwrócić tablicę struktur / C++ ?
» 2019-04-30 12:56:18
Witam, piszę program na zajęcia z C++, chciałbym aby funkcja usunPunkty zwróciła mi tablicę struktur ale nie do końca wiem jak się za to zabrać, proszę o pomoc.

C/C++
#include <iostream>
#include <string>
#include <conio.h>
#include <ctime>
#include <cstdlib>

using namespace std;


struct PUNKTY //deklaracja struktury
{
    int x;
    int y;
};

PUNKTY usunPowt( PUNKTY Plaszczyzna[] )
{
    int elem = 1000;
    int tablica1[ elem ];
    int tablica2[ elem ];
    for( int i = 0; i < elem; i++ )
    {
        tablica1[ i ] = Plaszczyzna[ i ].x;
        tablica2[ i ] = Plaszczyzna[ i ].y;
    }
   
    int licznik = 0;
    for( int i = 0; i < elem; i++ )
    {
        for( int j = i + 1; j < elem; j++ )
        {
            if( tablica1[ i ] == tablica1[ j ] )
            {
                if( tablica2[ i ] == tablica2[ j ] )
                {
                    tablica1[ i ] = - 1;
                    tablica2[ i ] = - 1;
                    licznik++;
                }
            }
        }
    }
   
    cout << "Liczba punktów, które się powtórzyły: " << licznik << endl;
   
    PUNKTY PlaszczyznaBezPowt[ elem - licznik ];
    int licznik2 = 0;
    for( int x = 0; x <( elem ); x++ )
    {
        if( tablica1[ x ] > - 1 )
        {
            PlaszczyznaBezPowt[ licznik2 ].x = tablica1[ x ];
            //cout << "New X:" <<PlaszczyznaBezPowt[licznik2].x<<" ";
           
            PlaszczyznaBezPowt[ licznik2 ].y = tablica2[ x ];
            //cout << "New Y:" << PlaszczyznaBezPowt[licznik2].y << " " << endl;
            licznik2++;
        }
        else
        {
        }
        return PlaszczyznaBezPowt[ licznik2 ];
    }
}
int main()
{
    system( "chcp 1250" );
   
    PUNKTY Plaszczyzna[ 1000 ]; //PUNKTY Plaszczyzna[1000];
   
    srand( time( NULL ) );
   
    for( int i = 0; i < 1000; i++ )
    {
        Plaszczyzna[ i ].x =( rand() % 800 ) + 1;
        Plaszczyzna[ i ].y =( rand() % 600 ) + 1;
    }
    usunPowt( Plaszczyzna );
   
    return 0;
}
P-174543
pekfos
» 2019-04-30 14:01:21
Nie da się zwrócić tablicy per se. Możesz:
  • zaalokować tablicę dynamicznie i zwrócić wskaźnik na nią,
  • zwrócić jeden obiekt, który zawiera w środku tablicę - osobną strukturę, std::array<>, albo std::vector<>,
  • przekazać tablicę jako argument i w funkcji ją wypełnić.

Twoja funkcja być może powinna wyglądać tak:
C/C++
int usunPowt( PUNKTY Plaszczyzna[], int rozmiar )
Powinieneś mieć przekazany rozmiar, zamiast go zgadywać w środku, a wynik możesz zapisać bezpośrednio do tablicy źródłowej. Jeśli możesz używać standardowych algorytmów, to std::sort(), potem std::unique() zrobią to, czego potrzebujesz. A jeśli nie, ale możesz używać standardowych kontenerów, to std::set<> jest wydajnym sposobem na testowanie, czy elementy się powtarzają. Oba podejścia dadzą czas O(n log n), twój aktualny algorytm ma O(n2) - dla 1000 elementów to tak poglądowo 100 razy wolniej.
P-174544
K1cek
Temat założony przez niniejszego użytkownika
» 2019-04-30 15:15:40
Czy ktoś mógłby mnie naprowadzić w jaki sposób utworzyć dynamiczną tablicę struktur i pokazać jak przekazać ją do funkcji usunPowt abym mógł ją wypełnić nowymi danymi ?
P-174545
pekfos
» 2019-04-30 17:47:11
Podałem 3 różne rozwiązania, nie listę kroków.
P-174546
nanoant20
» 2019-04-30 19:24:58
Czy ktoś mógłby mnie naprowadzić w jaki sposób utworzyć dynamiczną tablicę struktur i pokazać jak przekazać ją do funkcji ...

//edit teraz moze bardziej czytelnie

C/C++
#include <iostream>
#include <vector>   //for vector
#include <ctime>    //for srand

using namespace std;

struct PUNKTY
{
    int x;
    int y;
};

void addpoint( vector < PUNKTY > & tablica ) //przekazywac przez referencje
{
    PUNKTY p = { 200, 300 };
    PUNKTY r = { 10, 20 };
    PUNKTY s = { 100, 200 };
    tablica.push_back( p );
    tablica.push_back( r );
    tablica.push_back( s );
}

int main()
{
    vector < PUNKTY > tablica;
   
    //srand( time( NULL ) ); //warning
    srand( static_cast < unsigned int >( time( NULL ) ) );
    //srand( (unsigned int) time(NULL) );
   
    for( int i = 0; i < 10; i++ )
    {
        int a =( rand() % 80 ) + 1;
        int b =( rand() % 60 ) + 1;
       
        PUNKTY p = { a, b };
       
        tablica.push_back( p );
    }
   
   
    std::cout << std::endl;
    for( auto el: tablica )
         std::cout << el.x << ' ' << el.y << std::endl;
   
    std::cout << '\n';
   
    addpoint( tablica );
   
    for( auto el: tablica )
         std::cout << el.x << ' ' << el.y << std::endl;
   
    std::cout << '\n';
   
    std::cout << std::endl;
    //printing old way
    for( int i = 0; i < tablica.size(); i++ )
    {
        std::cout << tablica[ i ].x << " " << tablica[ i ].y << std::endl;
    }
   
    std::cout << std::endl;
    std::cin.get(); std::cin.get();
    return 0;
}
P-174547
nanoant20
» 2019-05-01 21:25:31
dlaczego nie ma progress'u?


C/C++
//add compiler flag -std=c++11 or -std=c++14 or higher
#include <iostream>
#include <vector>   //for vector
#include <ctime>    //for srand
#include <algorithm>

using namespace std;

struct PUNKTY
{
    int x;
    int y;
};
void addpoint( std::vector < PUNKTY > & tablica ); //prototyp funkcji

void addpoint( std::vector < PUNKTY > & tablica ) //przekazywac przez referencje
{
    PUNKTY p = { 21, 777 };
    PUNKTY r = { 100, 200 };
    PUNKTY s = { 21, 777 };
    tablica.push_back( p );
    tablica.push_back( r );
    tablica.push_back( s );
}

bool comp( const PUNKTY & a, const PUNKTY & b ) //modify
{
    return(( a.x < b.x ) ||( a.y < b.y ) );
}

int main()
{
    vector < PUNKTY > tablica;
   
    srand( static_cast < unsigned int >( time( NULL ) ) );
   
    /*ponizsza petelke zakomentowalem
        ale to ja nalezy uzyc w finalnym programie*/
    /*
        for( int i = 0; i < 10; i++ )
        {
            int a =( rand() % 80 ) + 1;
            int b =( rand() % 60 ) + 1;
   
            PUNKTY p = { a, b };
   
            tablica.push_back( p );
        }
        */
    //ta ponizsza petla posluzy mi do test'u
    for( int i = 0; i < 1; i++ )
    {
        PUNKTY a = { 20, 30 };
        PUNKTY b = { 10, 20 };
        PUNKTY c = { 100, 200 };
        tablica.push_back( a );
        tablica.push_back( b );
        tablica.push_back( c );
    }
   
    std::cout << "vector < PUNKTY > tablica; orginal" << std::endl;
    for( auto el: tablica )
         std::cout << el.x << ' ' << el.y << std::endl;
   
    std::cout << '\n';
   
    addpoint( tablica );
   
    std::cout << "Po dodaniu" << std::endl;
    for( auto el: tablica )
         std::cout << el.x << ' ' << el.y << std::endl;
   
    std::cout << '\n';
   
    sort( tablica.begin(), tablica.end(), & comp ); //modify
   
    std::cout << "po sortowaniu" << std::endl;
    for( int i = 0; i < tablica.size(); i++ )
    {
        std::cout << tablica[ i ].x << " " << tablica[ i ].y << std::endl;
    }
   
    std::cout << std::endl;
    std::cout << "rm - remove duplicates" << std::endl;
   
    auto compare =[]( const PUNKTY & a, const PUNKTY & b )
    {
        return(( a.x == b.x ) &&( a.y == b.y ) );
    };
    auto predykat =[]( const PUNKTY & a, const PUNKTY & b )
    {
        return(( a.x < b.x ) &&( a.y < b.y ) );
    };
    std::sort( tablica.begin(), tablica.end(), predykat );
    auto last = std::unique( tablica.begin(), tablica.end(), compare );
    tablica.erase( last, tablica.end() );
   
    for( int i = 0; i < tablica.size(); i++ )
    {
        std::cout << tablica[ i ].x << " " << tablica[ i ].y << std::endl;
    }
   
    std::cout << std::endl;
    std::cin.get();
    std::cin.get();
    return 0;
}

- uważam że program jest w miarę czytelny
- nalezy doszlifować i wgryźć się w temat,
- można wzbogacić funkcjonalność programu
- jeżeli są jakieś UWAGI to wprowadzić korektę
P-174548
pekfos
» 2019-05-01 22:05:13
uważam że program jest w miarę czytelny
nalezy doszlifować i wgryźć się w temat,
Kod nie jest zbyt czytelny, przez te "compare" i "predykat", nazwy są użyte więcej niż raz do nazwania różnych rzeczy i nawet nie w spójny sposób. I co ważniejsze - kod jest błędny, również z powodu predykatów. Polecam wgryźć się w wielką czerwoną ramkę na końcu » Kurs C++ » Poziom 5Wprowadzenie do standardowych algorytmów lekcja, jak również w przykładowy kod, w którym jest zaprezentowane, jak poprawnie sortować elementy po więcej niż jednej wartości.
C/C++
return(( a.x < b.x ) &&( a.y < b.y ) );
Taki predykat stawia a przed b wtedy, gdy obie wartości w a są mniejsze od tych w b. A jeśli jedna z tych wartości będzie równa, to dla sortowania a i b będą nieodróżnialne i posortowana sekwencja nie będzie poprawna dla std::unique(), a przynajmniej nie dla predykatu, jaki tam podałeś. Relacja równości dla std::unique() powinna być prawdziwa tylko i dla każdej pary elementów nierozróżnialnych przy sortowaniu, inaczej nie zawsze usuniesz duplikaty.
P-174549
nanoant20
» 2019-05-01 23:26:04
nazwy są użyte więcej niż raz
poprawiłem

Taki predykat stawia a przed b wtedy, gdy obie wartości w a są mniejsze od tych w b. A jeśli jedna z tych wartości będzie równa, to dla sortowania a i b będą nieodróżnialne i posortowana sekwencja nie będzie poprawna dla std::unique(),
zrozumiałem faktycznie jeżeli
PUNKTY b = { 100, 20 };
 nie zostanie posortowane, muszę przemyśleć

C/C++
auto predykat =[]( const PUNKTY & a, const PUNKTY & b )
{
    return(( a.x < b.x ) ||( a.y < b.y ) );
};

@pekfos tak zauważyłem
P-174550
« 1 » 2
  Strona 1 z 2 Następna strona