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

Wypełnienie tablicy n-losowymi liczbami z przedziału

Object Storage Arubacloud
+2 głosów
3,184 wizyt
pytanie zadane 12 listopada 2019 w C i C++ przez Tawka Nowicjusz (200 p.)

Hej, mam do wykonania program z tablicą 100-elementową, który pobiera najpierw rzeczywisty rozmiar n<= 100, a potem wypełnia tę tablicę losowymi liczbami typu int, z przedziału [a,b], który podaje użytkownik. Póki co mam coś takiego:

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;
int a;
int b;
int n;
int main()
{
     cout << "Podaj rozmiar tablicy <=100" << endl;
    cin >> n;
    if ( n> 100)
    {
        cout << "Podany rozmiar jest zbyt duzy. Podaj liczbe <=100" << endl;
    }
    else
        cout << "Podaj poczatek przedzialu liczb (0-100)" << endl;
    cin >> a;
    cout << "Podaj koniec przedzialu liczb (0-100)" << endl;
    cin >> b;
int tab[n];
cout << "Wylosowana tablica wynosi: " << endl;
for (int i = 0; i < n; i++)
{
tab[n] = (rand() % (b+1))- a;
cout << "tab[" << i << "]= " << tab[n] << endl;
}
char znak;
cin >> znak;
}

Problem polega na tym, że program wyświetla losowe liczby, ale nie zawsze z podanego przedziału, czasem zdarzają się nawet ujemne. Co robię źle?

1
komentarz 12 listopada 2019 przez tkz Nałogowiec (42,000 p.)
Źle to na pewno obchodzisz się z "dynamiczną" tablicą. Nie możesz od tak nadać jej rozmiaru. Rozmiar musi być stała, albo jak w tym przypadku musisz użyć new i delete. Dodaj przed ostatnią pętlą  srand(time(NULL));

3 odpowiedzi

+2 głosów
odpowiedź 12 listopada 2019 przez adrian17 Ekspert (344,860 p.)

ale nie zawsze z podanego przedziału, czasem zdarzają się nawet ujemne

(rand() % (b+1))- a;

Jeśli na przykład a==10, b==20:

  • rand() daje na przykład 1
  • 1 % (20+1) => 1
  • 1 - 10 => -9
2
komentarz 12 listopada 2019 przez mmarszik Mądrala (7,390 p.)
value = rand() % (max-min+1) + min;

 

0 głosów
odpowiedź 12 listopada 2019 przez mmarszik Mądrala (7,390 p.)
#include <iostream>
#include <vector>
#include <ctime>
#include <cstdlib>
#include <random>

static int getMin() {
    std::cout << "Podaj minimum przedziału: ";
    int n;
    std::cin >> n;
    if( std::cin.fail() ) {
        std::cout << "Niepoprawne dane" << std::endl;
        abort();
    }
    return n;
}

static int getMax(const int min) {
    std::cout << "Podaj maksimum przedziału: ";
    int n;
    std::cin >> n;
    if( std::cin.fail() || n < min ) {
        std::cout << "Niepoprawne dane" << std::endl;
        abort();
    }
    return n;
}

int main(int argc, char *argv[]) {
    std::vector<int> rnds;
    const int seed = (int)time(NULL);
    std::cout << "seed = " << seed << std::endl;
    const int min = getMin();
    const int max = getMax(min);
    std::ranlux48 generator( seed );
    std::uniform_int_distribution<int> distribution(min,max);
    for( int i=0 ; i<100 ; i++ ) {
        rnds.push_back( distribution(generator) );
    }
    for( int i=0 ; i<rnds.size() ; i++ ) {
        std::cout << (i+1) << " " << rnds[i] << std::endl;
    }
    return 0;
}

 

komentarz 12 listopada 2019 przez mmarszik Mądrala (7,390 p.)
Czermu downvote znowu? Złośliwość za pomoc? Program powinien działać?
komentarz 12 listopada 2019 przez tkz Nałogowiec (42,000 p.)
abort(); nie jest dobrym wyborem, ponieważ nie wywołuje destruktorów, w tym wypadku akurat nie ma to znaczenia, ale warto o tym pamiętać.
komentarz 12 listopada 2019 przez mmarszik Mądrala (7,390 p.)
A twórcy bibliotek standardowych i języków programowaia są w ciemie bici i zrobili abort bez wywołania destruktorów jakby to było potrzebne. Abort się używa gdy program ma się zakończyć w sposób nienormalny i tyle . Dodaj obsługę wyjątków jak Ci się chce, czepiać się jest łatwo. Ciekawe jaki sensowny kod wdestruktorach w tym minimalnym programie umieścisz? System i tak sam zwolni zasoby programu.
komentarz 12 listopada 2019 przez tkz Nałogowiec (42,000 p.)

https://en.cppreference.com/w/cpp/utility/program/abort

Abort się używa gdy program ma się zakończyć w sposób nienormalny i tyle 

Równie dobrze, mogłeś użyć return <kod błedu>;, albo właśnie wyjątków. 

Ciekawe jaki sensowny kod wdestruktorach w tym minimalnym programie umieścisz?

w tym wypadku akurat nie ma to znaczenia, ale warto o tym pamiętać.

Nie była to uwaga skierowana wyłącznie do Ciebie, a do pytającego. 

 

System i tak sam zwolni zasoby programu.

To po co używać delete?

komentarz 12 listopada 2019 przez mmarszik Mądrala (7,390 p.)

tkz:

1) Bym musiał rozbudować program, nie chciało mi się. Funkcja by musiała zwracać i wartość i informację czy operacja się powiodła - to już prościej wyjątków. To ma tylko naprowadzić pytającego jak mniej/więcej to się robi.

2) Co do delete to odruchowo użyłem, ale faktycznie tutaj nie jest potrzebne :)

3) Co do abrot, to można podpiąć jeszcze kod, który posprząta przed zakończieniem, co w dobrze napisanym programie, powinno być równoznaczne z wyjątkami i wywołaniem wszystkich destruktorów - ale to pisałem tylko tak aby mniej/więcej naprowadzić pytającego.

komentarz 12 listopada 2019 przez tkz Nałogowiec (42,000 p.)

W dobrze napisanym kodzie... To zależy. Dobry w jakim sensie? W świecie emdedded? Nie używa się wyjątków. 

2. punktu nie rozumiem.

System i tak sam zwolni zasoby programu.

To po co używać delete?

Pisząc to, miałem na myśli pytanie retoryczne, po co sprzątamy po sobie, skoro i tak wszystko system zwolni?

0 głosów
odpowiedź 12 listopada 2019 przez mmarszik Mądrala (7,390 p.)

Tutaj z dynamicznym rozmiarem, ale to można było samemu dorobić:

#include <iostream>
#include <vector>
#include <ctime>
#include <cstdlib>
#include <random>

static int getSize() {
    std::cout << "Podaj rozmiar: ";
    int n;
    std::cin >> n;
    if( std::cin.fail() || n < 1) {
        std::cout << "Niepoprawne dane" << std::endl;
        abort();
    }
    return n;
}


static int getMin() {
    std::cout << "Podaj minimum przedziału: ";
    int n;
    std::cin >> n;
    if( std::cin.fail() ) {
        std::cout << "Niepoprawne dane" << std::endl;
        abort();
    }
    return n;
}

static int getMax(const int min) {
    std::cout << "Podaj maksimum przedziału: ";
    int n;
    std::cin >> n;
    if( std::cin.fail() || n < min ) {
        std::cout << "Niepoprawne dane" << std::endl;
        abort();
    }
    return n;
}

int main(int argc, char *argv[]) {
    std::vector<int> rnds;
    const int seed = (int)time(NULL);
    std::cout << "seed = " << seed << std::endl;
    const int size = getSize();
    const int min = getMin();
    const int max = getMax(min);
    std::ranlux48 generator( seed );
    std::uniform_int_distribution<int> distribution(min,max);
    for( int i=0 ; i<size ; i++ ) {
        rnds.push_back( distribution(generator) );
    }
    for( int i=0 ; i<rnds.size() ; i++ ) {
        std::cout << (i+1) << " " << rnds[i] << std::endl;
    }
    return 0;
}

 

komentarz 12 listopada 2019 przez tkz Nałogowiec (42,000 p.)

Co do reserve i dlaczego warto. 

#include <cstddef>
#include <new>
#include <vector>
#include <iostream>
 
// minimal C++11 allocator with debug output
template <class Tp>
struct NAlloc {
    typedef Tp value_type;
    NAlloc() = default;
    template <class T> NAlloc(const NAlloc<T>&) {}
    Tp* allocate(std::size_t n) {
        n *= sizeof(Tp);
        std::cout << "allocating " << n << " bytes\n";
        return static_cast<Tp*>(::operator new(n));
    }
    void deallocate(Tp* p, std::size_t n) {
        std::cout << "deallocating " << n*sizeof*p << " bytes\n";
        ::operator delete(p);
    }
};
template <class T, class U>
bool operator==(const NAlloc<T>&, const NAlloc<U>&) { return true; }
template <class T, class U>
bool operator!=(const NAlloc<T>&, const NAlloc<U>&) { return false; }
 
int main()
{
    int sz = 100;
    std::cout << "using reserve: \n";
    {
        std::vector<int, NAlloc<int>> v1;
        v1.reserve(sz);
        for(int n = 0; n < sz; ++n)
            v1.push_back(n);
    }
    std::cout << "not using reserve: \n";
    {
        std::vector<int, NAlloc<int>> v1;
        for(int n = 0; n < sz; ++n)
            v1.push_back(n);
    }
}

https://pl.cppreference.com/w/cpp/container/vector/reserve

komentarz 12 listopada 2019 przez mmarszik Mądrala (7,390 p.)
Jeśli to jest do mnie, to ja wiem że warto i to z kilku powodów. Nie użyłem tutaj bo mi się nie chciało i są to programy przykładowe. Niektórzy piszą że nawet wektora nie ma sensu używać jak to tylko 100 elementów, a swoich allokatorów i reserwe - warto :)
komentarz 12 listopada 2019 przez mokrowski Mędrzec (155,460 p.)

@mmarszik, to jest bardzo proste. Jak będę miał uwagi, to się nimi podzielę. Jak Ty będziesz miał uwagi, to także się nimi podziel. Jeśli dla Ciebie jest to "czepialstwo" i "atak na godność", to niewiele mnie to obchodzi jeśli utrzymuję pewien poziom kultury wypowiedzi i odnoszę się do meritum.

Co do std::endl

https://www.geeksforgeeks.org/avoid-using-stdendl/

https://stackoverflow.com/questions/35580919/should-stdendl-always-be-used

https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#Rio-endl

W linku podanym przez kolegę: https://stackoverflow.com/questions/213907/c-stdendl-vs-n , przeczytaj następne zdanie po tym które cytowałeś. Brzmi ono:

If you don't want the buffer flushed frequently, use '\n'.

Co do reserve(), kolega dał odpowiedź.

 

komentarz 12 listopada 2019 przez mmarszik Mądrala (7,390 p.)
Miło że masz uwagi, ale zanim się nimi podzielisz, to wczuj się trochę w moją rolę. Przecież nie zwraca się uwagi sprinterowi że słabo rzuca oszczepem. Tak samo niekoniecznie musisz zwracać mi uwagę na elementy które (zazwyczaj) rozumiem, a nie używam ich tutaj bo programy piszę za free w celach poglądowych, a już na pewno nie w celach optymalizacyjncyh. Poza tym optymalizacja (jeśli jest niekonieczna) to w każdej firmie uznawana jest za bardzo złą prakykę.
komentarz 12 listopada 2019 przez mmarszik Mądrala (7,390 p.)

[

If you don't want the buffer flushed frequently, use '\n'.

]

To jest nadal to samo, zwracasz uwagę sprinterowi że słabo rzuca oszczepem. Dlaczego zakładasz że ja nie chcę aby bufor był często opróżniany? Ja chcę i to bardzo!

 

Podobne pytania

0 głosów
3 odpowiedzi 28,548 wizyt
pytanie zadane 3 grudnia 2017 w C i C++ przez SzaaBao Początkujący (380 p.)
0 głosów
1 odpowiedź 1,213 wizyt
pytanie zadane 9 stycznia 2018 w C i C++ przez Tomek112 Początkujący (310 p.)
0 głosów
2 odpowiedzi 3,274 wizyt

92,556 zapytań

141,404 odpowiedzi

319,560 komentarzy

61,942 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!

...