deklaracja tablicy dynamicznej

deklaracja tablicy dynamicznej
G1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 52
0

Proszę o informację jak zadeklarować tablicę dynamiczną znając jej elementy.

Althorion
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1620
5

Używanie dynamicznych tablic (zamiast, na przykład, std::vector czy podobnych) to rozwiązanie sprzed półwiecza i proszenie się o kłopoty.

Tym niemniej, jeśli prowadzący ciśnie, albo ktoś Cię porwał i nie wypuści, dopóki tak nie zakodzisz, to można zdziałać coś takiego:

Kopiuj
auto tablica = std::make_unique<TYP[]>(LICZBA_ELEMENTÓW);

(lub std::make_shared, w ramach potrzeb)

Gdzie, oczywiście, TYP to typ tych znanych elementów, a LICZBA_ELEMENTÓW to ich liczba.


A jak ktoś chce używać new[], to niech się sam męczy.

G1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 52
0
Althorion napisał(a):

Używanie dynamicznych tablic (zamiast, na przykład, std::vector czy podobnych) to rozwiązanie sprzed półwiecza i proszenie się o kłopoty.

Tym niemniej, jeśli prowadzący ciśnie, albo ktoś Cię porwał i nie wypuści, dopóki tak nie zakodzisz, to można zdziałać coś takiego:

Kopiuj
auto tablica = std::make_unique<TYP[]>(LICZBA_ELEMENTÓW);

(lub std::make_shared, w ramach potrzeb)

Gdzie, oczywiście, TYP to typ tych znanych elementów, a LICZBA_ELEMENTÓW to ich liczba.


A jak ktoś chce używać new[], to niech się sam męczy.

Althorion napisał(a):

Używanie dynamicznych tablic (zamiast, na przykład, std::vector czy podobnych) to rozwiązanie sprzed półwiecza i proszenie się o kłopoty.

Tym niemniej, jeśli prowadzący ciśnie, albo ktoś Cię porwał i nie wypuści, dopóki tak nie zakodzisz, to można zdziałać coś takiego:

Kopiuj
auto tablica = std::make_unique<TYP[]>(LICZBA_ELEMENTÓW);

(lub std::make_shared, w ramach potrzeb)

Gdzie, oczywiście, TYP to typ tych znanych elementów, a LICZBA_ELEMENTÓW to ich liczba.


A jak ktoś chce używać new[], to niech się sam męczy.

Proste zadanko z pl.spoj.com. Próbuję zejść z czasu 0.01 za 'liczby pierwsze'.

Althorion
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1620
1

To używaj std::vector jak człowiek współczesny, będzie grało. SPOJ nie wymaga nanooptymalizacji, a trudniej Ci będzie o błędy. Wyrabianie dobrych nawyków też się wtedy liczyć będzie na plus.

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
3
gaborek1987 napisał(a):

Proste zadanko z pl.spoj.com. Próbuję zejść z czasu 0.01 za 'liczby pierwsze'.

Lepiej pokaż swoje rozwiązanie.
Zadania na SPOJ mają to do siebie, że niektóre optymalizacje wymagają pomyślunku (lepszego algorytmu), a inne tylko optymalizacji operacji IO.

Standardowa optymalizacja IO (wywołać na początku `main):

Kopiuj
void setupIO()
{
    std::ios::synch_with_stdio(false);
    std::cin.tie(nullptr);
}

Zastąpienie wszystkich std::endl przez '\n'.

tBane
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Poznań
  • Postów: 540
0

Ja bym użył std::vector < Int > tablica;

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
3

Tu masz generator liczb pierwszy w czasie kompilacji:
https://wandbox.org/permlink/ODZ2TL4VgjJv6b0c

Jako, że widzę, że na SPOJ limit to 10000 to takie rozwiązanie jest najlepsze.

CZ
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2553
1
gaborek1987 napisał(a):

Proste zadanko z pl.spoj.com. Próbuję zejść z czasu 0.01 za 'liczby pierwsze'.

Pokaż kod. Może tracisz czas na niepotrzebne kopie, albo cin/cout zostawiłeś. Brak paru ampersandów może zmienić wszystko.

G1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 52
0
Czitels napisał(a):
gaborek1987 napisał(a):

Proste zadanko z pl.spoj.com. Próbuję zejść z czasu 0.01 za 'liczby pierwsze'.

Pokaż kod. Może tracisz czas na niepotrzebne kopie, albo cin/cout zostawiłeś. Brak paru ampersandów może zmienić wszystko.

Kopiuj
#include <iostream>
using namespace std;
bool all[10001];
struct prim {
    int x;
    prim* next;
};

struct lista {
    prim* first;
    prim* last;
    void add(int y);
};

void lista::add(int y)
{
    prim* a = new prim;
    a->x = y;
    prim* one = last;
    (one->next) = a;
    last = a;
}

int b, m;
int main()
{
    //  for(int i=1;i<10000;i++)all[i]=false;
    lista* l = new lista;
    prim* one = new prim;
    one->x = 3;
    l->first = one;
    l->last = one;
    all[2] = true;
    all[3] = true;
    prim* liczba;
    for (int i = 5; i < 99; i += 2) {
        b = 3;
        liczba = (l->first);

        while (b * b < i && i % b != 0) {
            liczba = (liczba->next);
            b = liczba->x;
        }
        if (b * b > i) {
            l->add(i);
            all[i] = true;
        }
    }
    l->add(101);
    all[101] = true;
    for (int i = 103; i < 10000; i += 2) {
        b = 3;
        liczba = (l->first);

        while (b * b < i && i % b != 0) {
            liczba = (liczba->next);
            b = liczba->x;
        }
        if (b * b > i)
            all[i] = true;
    }
    int k, n;
    scanf("%d", &m);
    while (m > 0) {
        m--;
        scanf("%d", &b);
        if (all[b])
            printf("TAK\n");
        else
            printf("NIE\n");
    }
}
MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
1

Po co ci ta lista skoro masz już bool all[10001];?
Lecisz z sitem Eratostenesa, a potem sprawdzasz dane wejściowe w sicie.
Żadna lista nie jest potrzebna.

G1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 52
0

Po co ci ta lista skoro masz już bool all[10001];?
Lecisz z sitem Eratostenesa, a potem sprawdzasz dane wejściowe w sicie.
Żadna lista nie jest potrzebna.

To rozwiązanie z dnia: 2024-08-26

G1
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 52
0

Wysłałem to w 2024-08-26 . Lista była niezbędna.

CZ
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 2553
0
gaborek1987 napisał(a):

Wysłałem to w 2024-08-26 . Lista była niezbędna.

Po co niezbędna? Plus zauważyłem jedną rzecz. Nie pamiętam dokładnie sita, ale po co zaczynasz od b=3 i wykonujesz operacje od nowa? Nie możesz bazować na poprzednich?

Kopiuj
        b = 3;
        liczba = (l->first);

        while (b * b < i && i % b != 0) {
            liczba = (liczba->next);
            b = liczba->x;
        }
wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 683
0

a nie łatwiej tak;

Kopiuj
int total=100;
char *data=new char[total];;

a po wykorzystaniu zmiennej żeby zwolnić bufor to:

Kopiuj
delete data;

jeśli elementy mają być jedno bajtowe a dla int

Kopiuj
int *data=new int[total];;

i float:

Kopiuj
float *data=new float[total];

elementy są 4 bajtowe

MarekR22
  • Rejestracja: dni
  • Ostatnio: dni
5
wilkwielki napisał(a):

a nie łatwiej tak;

NIE.
Chyba, że cofniesz się do lat '90.

MY
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1107
4
wilkwielki napisał(a):

a nie łatwiej tak;

Kopiuj
int total=100;
char *data=new char[total];;

a po wykorzystaniu zmiennej żeby zwolnić bufor to:

Kopiuj
delete data;

Jak już odpowiadasz na pytanie, to przynajmniej nie wprowadzaj w błąd. Nie tak się zwalnia pamięć przydzielaną w ten sposób.

Tworzysz za pomocą new [] to zwalniasz za pomocą delete []

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 683
0

przecież operator new i delete jest znany od wieków i działa do dzisiaj, sam tak wykorzystuje bufforowanie danych

BR
  • Rejestracja: dni
  • Ostatnio: dni
  • Lokalizacja: Kraków
  • Postów: 32
2
wilkwielki napisał(a):

przecież operator new i delete jest znany od wieków i działa do dzisiaj, sam tak wykorzystuje bufforowanie danych

tak samo jak lampa naftowa. Mimo to ludzie używają żarówek (jeżeli mają prąd). Poza tym ignorujesz komentarz Mr.YaHooo.

Dwa przykłady:

https://godbolt.org/z/aPxbd43xY

Kopiuj
#include <iostream>

class Test {
public:
    Test() { std::cout << "Konstruktor\n"; }
    ~Test() { std::cout << "Destruktor\n"; }
};

int main() {
    Test* ptr = new Test[3]; // Alokujemy tablicę 3 obiektów

    delete ptr; // ❌ BŁĄD! Powinno być delete[]
    
    return 0;
}

Z odpowiednimi flagami się nawet nie skompiluje. Bez flag po prostu nie działa (SIGSEGV). Najprawdopodobniej wywołało by destruktor tylko dla pierwszego elementu. Wyciek i/lub niedozwolony dostęp do pamięci.

https://godbolt.org/z/xYsMT1Tc3

Kopiuj
#include <iostream>

int main() {
    int* arr = new int[5];  // Alokujemy tablicę
    delete arr;  // ❌ UB – powinno być delete[]

    return 0;
}

Tu jak wyżej. Z odpowiednimi flagami się nawet nie skompiluje. Bez flag wygląda że działa ale to nie znaczy że jest dobrze. To bardziej przypadek, a nie gwarancja. Wyciek i/lub niedozwolony dostęp do pamięci i tak być może. Poza tym to chyba niezdefiniowane zachowanie.

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 683
0

z mojej strony to jest tak ze zawsze wywołuje samo delete i zwalnia buffor starczy wrzucić w petle new i delete i nie bedzie przeciązenia stosu , cały mój framework bazuje na samym operatorze delete i działa niezawodnie pierwsze raz słyszę że trzeba podawać po delete klamry, to nawet jeśli to było by tak ze po delete daje się klamrę to na jakiej wersji c++ działacie , ja korzystam z vc++6.0 Pro z c++98 i wszystko hula dobrze, dla mnie to dziwne

Spearhead
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1007
3

https://isocpp.org/wiki/faq/freestore-mgmt#delete-array-built-ins

Can I drop the [] when deleteing an array of some built-in type (char, int, etc)?

No!

Sometimes programmers think that the [] in the delete[] p only exists so the compiler will call the appropriate destructors for all elements in the array. Because of this reasoning, they assume that an array of some built-in type such as char or int can be deleted without the []. E.g., they assume the following is valid code:

Kopiuj
   void userCode(int n)
   {
     char* p = new char[n];
     // ...
     delete p;     // ← ERROR! Should be delete[] p !
   }

But the above code is wrong, and it can cause a disaster at runtime. In particular, the code that’s called for delete p is operator delete(void*), but the code that’s called for delete[] p is operator delete[](void*). The default behavior for the latter is to call the former, but users are allowed to replace the latter with a different behavior (in which case they would normally also replace the corresponding new code in operator new[](size_t)). If they replaced the delete[] code so it wasn’t compatible with the delete code, and you called the wrong one (i.e., if you said delete p rather than delete[] p), you could end up with a disaster at runtime.

wilkwielki
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 683
0

z tego co widze to są po prostu różnice kodo zmianowe, diabeł tkwi w wersjach c++ i tyle po prostu z mojej stony

MY
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1107
3
wilkwielki napisał(a):

z mojej strony to jest tak ze zawsze wywołuje samo delete i zwalnia buffor starczy wrzucić w petle new i delete i nie bedzie przeciązenia stosu , cały mój framework bazuje na samym operatorze delete i działa niezawodnie pierwsze raz słyszę że trzeba podawać po delete klamry, to nawet jeśli to było by tak ze po delete daje się klamrę to na jakiej wersji c++ działacie , ja korzystam z vc++6.0 Pro z c++98 i wszystko hula dobrze, dla mnie to dziwne

A dla mnie jest dziwne, bo w każdej książce z jaką miałem do czynienia odnośnie C++ pisali, że pamięć zaalokowaną przez new zwalniamy przez delete. Natomiast new[] implikuje późniejsze użycie delete[].

Ale ok, możesz mi nie wierzyć. Skoro wyciągasz ciężkie działo w postaci standardu C++, więc szukamy.
https://en.cppreference.com/w/cpp/links
Masz tam sekcję C++ standard documents and drafts
Następnie używam linka: N1146 (PDF) - C++98 final working draft.
Znajduję się tu: https://open-std.org/JTC1/SC22/WG21/docs/wp/pdf/nov97-2/
Dalej idę tu: https://open-std.org/JTC1/SC22/WG21/docs/wp/pdf/nov97-2/body.pdf

Przeglądam PDF'a i mam całą sekcję poświęconą operatorowi delete. Na samym początku pisze jak wół:

5.3.5 Delete
1 The delete-expression operator destroys a most derived object (1.7) or array created by a new-expression.
delete-expression:
::opt delete cast-expression
::opt delete [ ] cast-expression
The first alternative is for non-array objects, and the second is for arrays. The operand shall have a pointer type, or a class type having a single conversion function (12.3.2) to a pointer type. The result has type void

Więc jak widzisz cały Twój framework który bazuje na samym operatorze delete jest wbrew standardowi. To, że działa to po prostu szczęście. Po prostu pamięć Ci ucieka, a Ty nawet tego nie sprawdzałeś. Więc nie są to żadne różnice "kodo zmianowe" (w ogóle co to oznacza?) a zwykłe szczęście.

Spearhead
  • Rejestracja: dni
  • Ostatnio: dni
  • Postów: 1007
1

To macie jeszcze screenshoot z książki Stroustrupa "Projektowanie i rozwój języka C++"

screenshot-20250129162315.png

Wersja C++ 2.0 to według wiki 1989 rok, 9 lat nim powstał pierwszy standard.

RE
  • Rejestracja: dni
  • Ostatnio: dni
0

a wy nie rozmawiacie z alter ego tego innego gościa od visual c++ 6 z roku 2002? bo jak patrzę to dwa konta pisza o tym samym ale modzi by musieli sprawdzić czy to nie ten sam ip.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.