Początki programowania

Początki programowania
admaj1212
  • Rejestracja:około 6 lat
  • Ostatnio:ponad 5 lat
  • Postów:2
0

Witam
Robię kurs i spotkałem takie zadanie:
Napisz funkcję, która losuje liczbę z przedziału od 50 do 60 włącznie. Wywołaj funkcję kilka razy (wypisz wylosowane wartości na ekran) w celu przetestowania czy działa ona poprawnie.
I zrobiłem tak i nie działało:

Kopiuj
#include <iostream>
#include <cstdlib>
#include  <ctime>
using namespace std;
void losuj(){
    srand(time(NULL));
    cout<<(rand()%11)+51;
}
int main()
{
    losuj();
    cout<<endl;
    losuj();
    cout<<endl;
    losuj();

    return 0;
}

Trochę nad tym siedziałem i doszedłem do wniosku że Funkcja srand musi być w funkcji main wtedy działa. Może ktoś wytłumaczyć czemu tak się dzieje?

edytowany 1x, ostatnio: flowCRANE
D1
  • Rejestracja:około 6 lat
  • Ostatnio:prawie 6 lat
  • Postów:14
1

No faktycznie tak jest ciekawe... no ale widocznie tak to działa PS twój program nie losuje liczb z dobrego przedziału(losuje od 51 do 61 włącznie). dodałem ci jeszcze pętle bo tak jest wygodniej

Kopiuj
#include <iostream>
#include <cstdlib>
#include  <ctime>
using namespace std;
void losuj(){

    cout<<(rand()%11)+50;
}
int main()
{
 srand(time(NULL));
	for(int i=0;i<3;i++)
	{
		losuj();
    cout<<endl;
	}


    return 0;
}
edytowany 1x, ostatnio: dorn111
admaj1212
Ooooooooo no tak nie zobaczyłem..(sugerowałem się jak kiedyś robiłem zadanie i żeby od zera nie losować to dodawało się jedynkę i tu tak z odruchu dodałem, ale wiem o co chodzi) Dzięki wielkie :)
Stefan_3N
  • Rejestracja:około 6 lat
  • Ostatnio:18 dni
  • Postów:145
4

rand losuje liczbę.
srand inicjalizuje generator liczb pseudolosowych.
Jeśli przed wywołaniem rand nie dasz w ogóle srand, to za każdym razem podczas uruchomienia programu będziesz miał wylosowaną taką samą sekwencję liczb.
Tę sekwencję zmieniasz właśnie za pomocą srand (pod warunkiem, że argument podany do srand jest różny od 1).
Ty jako argument podajesz wynik działania funkcji time(NULL). Funkcja time zwraca liczbę sekund, które upłynęły od 01.01.1970.
Jeśli Twój komputer jest szybki i nie miałeś szczęścia, to kolejne wywołania Twojej funkcji losuj() wykonywały się w tej samej sekundzie. W konsekwencji srand inicjalizował generator tą samą wartością. Nie sprawdzałem tego programu, ale pewno dostawałeś trzy takie same liczby. Przy ponownym uruchomieniu - kolejne trzy (ale inne). Przy odrobinie szczęścia, kolejne dwa wywołania wykonałyby się w innej sekundzie i wtedy dwie byłyby takie same, a trzecia inna.

Zwróć też uwagę na funkcję time(), która zwraca wartość zarówno wprost, jak i przez wskaźnik (który u Ciebie jest NULL).
Czasem są pytania po co taka możliwość. Jedni mówią, że to zaszłość historyczna (w systemach 16-bitowych wartość zwracana z funkcji byłaby 16-bitowa, tymczasem time_t - to minimum 32 bity).

Ale takie rozwiązanie umożliwia też taką konstrukcję:

time_t t;
time_t v=time(&t)-cośtam;

W takim rozwiązaniu w jednym ruchu odczytujesz czas bieżący i jednocześnie możesz obliczyć jakąś różnicę czasu.

Rozwiązanie z srand(time(NULL)) w main nie jest złe w Twoim przykładzie, ale gdybyś to umieścił w jakimś większym kodzie, to nadal mogłoby być tak, że kolejne wywołania wykonywałyby się w tej samej sekundzie i losowość byłaby taka sobie.


admaj1212
Tak tak właśnie 3 takie same ale za każdym razem inne dzięki za podpowiedź :)
admaj1212
Mógłbyś pomóc niżej?
admaj1212
  • Rejestracja:około 6 lat
  • Ostatnio:ponad 5 lat
  • Postów:2
0

Witam znowu napotkałem na taki dziwny problem. Napisałem funkcjię losującą która wpisuje losowe liczby do tablicy a na końcu ma ich zsumować. Przy sumowaniu pętlą do{}while sumowało źle a pętlą for dobrze. Jest jakieś wytłumaczenie na to?

Pętla for która działa:

Kopiuj
void losuj(){
    int liczba[9];
    int licznik = 0;
do{

    liczba[licznik]=(rand()%7)+4;
    cout<<liczba[licznik]<<endl;
    licznik++;
    }while(licznik<10);
int suma = 0;
for(int licznik=0; licznik<10;licznik++){
    suma+=liczba[licznik];
    }
cout<<suma<<endl;
}

A tutaj pętla do{}while:

Kopiuj
void losuj(){
    int liczba[9];
    int licznik = 0;
do{

    liczba[licznik]=(rand()%7)+4;
    cout<<liczba[licznik]<<endl;
    licznik++;
    }while(licznik<10);
licznik=0;
int suma = 0;
do{
    suma+=liczba[licznik];
    licznik++;
    }while(licznik<10);
cout<<suma<<endl;
}
edytowany 1x, ostatnio: admaj1212
D1
Pierwszy błąd jaki znalazłem to długość pętli tablice liczymy od 0 a nie 1 czyli tu jest przypisanie wartości do elementu nie będącego w tablicy. (liczba[9])
admaj1212
Dzięki wielkie :)
D1
  • Rejestracja:około 6 lat
  • Ostatnio:prawie 6 lat
  • Postów:14
1
Kopiuj
#include <iostream>
#include <cstdlib>
#include  <ctime>
using namespace std;
void losuj(){
    int liczba[9];
    int licznik = 0;
do{

    liczba[licznik]=(rand()%7)+4;
    cout<<liczba[licznik]<<endl;
    licznik++;
    }while(licznik<9);//do 9 bo liczymy od zera
int suma = 0;
for(int licznik=0; licznik<9;licznik++)//musi być do 9 bo liczymy 9 argumentów od 0.
{ 
    suma+=liczba[licznik];
    }
cout<<suma<<endl;
}
int main()
{
 srand(time(NULL));
    losuj();
    

    return 0;
}
//PS Mi oba programy nie działały :)
//PPS A nie jednak ten drugi działa ale nie wiem czemu... bo nie powinien może znajdę przyczynę
//PPPS No nie wiem czemu ten drugi program działa i to jeszcze za każdym razem... nie powinien działać widocznie kompilator //zapisuje gdzieś w pamięci tą dodatkową wartość i następnie ją odczytuje,czasem tak bywa, ogólnie to jedyny błąd to 10 zamiast 9
edytowany 2x, ostatnio: dorn111
admaj1212
Dzięki uczę się i trochę jeszcze tak tego nie ogarniam ale powoli dam radę 😂
Stefan_3N
  • Rejestracja:około 6 lat
  • Ostatnio:18 dni
  • Postów:145
1

Dorn już zauważył rozmiar tablicy, ale skoro napisałem list, to go wkleję :-)

C nie jest prostym językiem ze względu na to, że wielu oczywistych pomyłek kompilator nie zgłasza.

masz deklarację
int liczba [9];
to znaczy, że masz 9 elementów w tablicy (nie 10). Elementy w tablicy będę miały indeksy od 0 do 8.
A Twoje pętle przebiegają od 0 do 9. Czyli sięgasz po element liczba[9], który nie istnieje.
Kompilator tego nie zgłosi.

Czemu raz działa, a innym razem nie?
W pamięci zmienna "liczba" - to jest obszar

Kopiuj
9 * sizeof(int) bajtów.

(sizeof(int) podaje Ci rozmiar w bajtach zmiennej typu int. Ile to będzie konkretnie - to zależy od środowiska. W Windowsie 16-bitowym - to były 2 bajty, w Win32 - 4 bajty, na Linuxie - nie wiem).
Załóżmy, że działasz na Win32. Wtedy Twoja zmienna "liczba" - to jest ciągły obszar pamięci o długości 36 bajtów (9 * 4).
Dla kompilatora (i de facto dla Ciebie) - to jest jednolity obszar pamięci (bajtów).

Możesz np. napisać tak:

Kopiuj
char* t=(char*)liczba;

(to się nazywa rzutowanie typów. Zrzutowałeś typ int na typ char. I teraz pod zmienną t masz ten sam obszar pamięci, ale traktowany jak tablicę znaków, czyli upraszczając bajtów).

I dalej możesz spokojnie napisać t[12]=coś tam
W ten sposób do 13 bajtu tego obszaru wpakujesz "coś tam"
Ale - równie dobrze możesz napisać t[1250]=nowa wartość
Kompilator nie mrugnie, a Ty zapakujesz "nową wartość" do zupełnie innego obszaru pamięci. Rozumiesz?
W tym przykładzie dozwolone będzie t[35]=0, bo to jest ostatni bajt w Twoim zarezerwowanym obszarze.
t[36], to jest pierwszy bajt za zarezerwowanym obszarem. Jeśli w Twoim programie w tym miejscu nie ma żadnych istotnych (innych) danych, to nic się nie stanie. Będzie działać i da dobry wynik.

Wracając do int. To działa tak samo jak tablica bajtów, tylko ze kompilator sam "skacze" po bajtach przesuwając miejsce zapisu do położenia index*sizeof(typ)
Czyli jeśli masz:
int tablica[9], to tablica[2]=12 oznacza, że kompilator zapakuje 12 w cztery bajty poczynając od ósmego (faktycznie tylko jeden bajt będzie miłą wartość 12, a kolejne trzy będą zerami).
W twoim programie - w pętlach w pewnym momencie w czasie wykonywania programu dochodzi do sytuacji
suma+=tablica[9];
W tym momencie następuje pobranie czterech bajtów poczynając od 36 pozycji (licząc w bajtach). A tam może być dowolna wartość, bo twoim ostatnim zarezerwowanym bajtem jest komórka 35.

Reszta (działanie lub nie, ewentualne zawieszenia programu i różne dziwne zachowania) to już jest kwestia przypadku. To będzie zależało od tego, co się znajduje w obszarze do którego się odwołujesz, czy tylko czytasz, czy może próbujesz coś zapisać, itd.

W tych programach jest jeszcze jedna sprawa, na którą można zwrócić uwagę.
W wersji z for zmienna licznik jest deklarowana dwa razy. Raz na początku, i potem w pętli for.
Czy tak można, czy nie - to zależy od konkretnej wersji kompilatora. Niektóre na to pozwolą inne wykażą błąd ("zmienna już zadeklarowana").
A niektóre kompilatory mają nawet opcję konfiguracyjną. W każdym razie proponuję unikać takich sytuacji i nie deklarować dwóch zmiennych o tej samej nazwie w ramach jednej funkcji.


admaj1212
Dzięki wielkie , mniej więcej wiem o co chodzi 😊 przyda się na przyszłość, jeszcze raz dzięki 😀
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)