Zaloguj się, aby obserwować  
UthersonL

Programowanie - pytania, problemy, przykłady programów

1812 postów w tym temacie

Dnia 04.11.2009 o 14:48, Choinix napisał:

Jeżeli się mylę to proszę mnie oświecić, ale już nie raz potrzebowałem obliczyć silnię
w swoich programach i musiałem korzystać z tego.


Dzięki :)
Po wielu przejrzanych stronach właśnie takie rozwiązanie okazało się być najlepszym wyjściem.

Udostępnij ten post


Link to postu
Udostępnij na innych stronach
Dnia 04.11.2009 o 18:47, scooby01 napisał:

Po wielu przejrzanych stronach właśnie takie rozwiązanie okazało się być najlepszym wyjściem.

W programach, które rzeczywiście potrzebują używać silni - czyli najczęściej statystycznych wyliczone wartości dla poszczególnych n cachuje się po to aby przy kolejnym odczycie dla wcześniej wyliczonych wartości nie obliczać ich ponownie (co jest piekielnie czasochłonne), ale sięgać po prostu do komórki tablicy.
A najkrótszy kod tej funkcji jaki znam, zgodny z C, C++ i Javą jest taki:
long silnia(long n)
{
long wynik = 1;
while(n > 0) wynik *= n--;
return wynik;
}
Dla ujemnych n oraz n = 0 wynikiem jest 1.

Udostępnij ten post


Link to postu
Udostępnij na innych stronach
Dnia 27.10.2009 o 22:22, ziptofaf napisał:

No to ja mam takie nietypowe pytanie dot. C++. Mianowicie robię program, który najpierw
wczytuje liczbę tablic/wektorów do stworzenia, potem ich wielkość, a potem same wartości
wewnątrz. I pojawia mi się problem - mianowicie jak generować te kolejne wektory? Bo
chyba nie da się ich w żaden sposób nazwać, więc pozostają mi chyba tylko new i wskaźniki.
No i ja niestety jestem dość beznadziejny w tej dziedzinie - czy jedynym sposobem byłoby
stworzenie też dodatkowej tablicy int przechowującej adresy każdego z tych wektorów)?

W Javie byłoby to dość proste, ale w C++ pozostaje Ci utworzenie klasy Wektor ze zmienną liczbą argumentów w konstruktorze, która tworzyłaby tablice tablic o ilości zgodnej z liczbą wymiarów oraz wartością każdego wymiaru (czyli podtablicy). Generalnie mnóstwo zagnieżdżonych pętli for. Wszystkie tablice powinny być zrealizowane klasą vector z biblioteki std - głównie z tego powodu, że ma ona zmienną długość, nie ma limitu elementów i wszystko może siedzieć na stercie.
Generalnie jedynym sposobem unikania jawnych wskaźników jest posługiwanie się tablicami dynamicznymi czyli właśnie klasą vector.
Poszczególne wektory też powinieneś trzymać w osobnej tablicy i podobnie w tym przypadku też warto użyć klasy vector.
Istotne jest, żebyś sensownie nazywał zmienne oraz metody prywatne - to wtedy się nie pogubisz.

Dnia 27.10.2009 o 22:22, ziptofaf napisał:

I jeszcze jedno pytanie - jak się robiło wskaźnik na wektor/tablicę? I jak w tym momencie
wprowadzać do niej wartości?

Dla tablicy int tablica[] formalnie wskaźnikiem jest int (*wskaznik_tablicy)[]. Jednak bardziej użyteczne jest po prostu użycie int *wskaznik_elementu = tablica bo nazwa tablicy jest zawsze wskazaniem do pierwszego jej elementu. Czyli: tablica == &tablica[0] jest prawdziwe. A co do nadawania wartości, to *wskaznik_elementu = wartość lub (*wskaznik_tablicy)[indeks] = wartość. Z tym, że jak już napisałem używanie wbudowanych tablic w C/C++ to ostatnia rzecz jaką bym Ci proponował do czegokolwiek. Tak naprawdę jest to najbardziej zwalona część języka C i tablice w tym języku nadają się jedynie do użycia jako proste jednowymiarowe agregaty zmiennych. W innym wypadku to strata czasu ponieważ na eliminację błędów w kodzie obsługującym tablice poświęcisz 3 razy więcej czasu niż będziesz miał.

A jak chcesz dowiedzieć się czegoś z forum tematycznego, to warto skoczyć choćby tu:
http://forum.4programmers.net

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

/.../
Szczerze mówiąc, jakoś sobie już z tym poradziłem, właśnie za pomocą wskaźników:
int *adres; // zmienna pomocnicza
int tab_maker(int il_el){
int * const d = new int[il_el-1];
for (int i=0; i<=il_el-1; i++)
{
cin >> d; - tu miało być [ i ], ale gram.pl to traktuje jako kursywę.
}
adres=d; // przypisywanie adresu tablicy

A o tej własności wektorów, że mogą zmieniać rozmiar, nie pomyślałem. A szkoda, bo bym ułatwił sobie pisanie.

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

Dobra, mój program (post wyżej znajduje się kod) wariuje. Wystarczy kazać mu zrobić takie tablice:

5 (rozmiar tablicy)
1 5 5 8 6
3 (rozmiar tablicy)
2 2 2
3 (rozmiar tablicy)
5 7 8

By wszystko skończyło się spektakularnym padem programu. Na Windowsie. Na Linuxie całość działa poprawnie, nawet jeśli próbuję bezpośrednio uruchamiać plik .exe przez Wine, co jest w końcu tylko emulacją...Podejrzewam, że chodzi o pamięć na stosie funkcji (destruktor dostawiłem dopiero pod koniec instrukcji main, bo będę przecież tych tablic używać przez resztę działania programu), ale jeśli tak jest, to nie mam pojęcia co z tym zrobić. Da się jakoś poprawić ten kod, żeby działał normalnie, a nie wariował?

Udostępnij ten post


Link to postu
Udostępnij na innych stronach
Dnia 05.11.2009 o 01:53, ziptofaf napisał:

By wszystko skończyło się spektakularnym padem programu. Na Windowsie. Na Linuksie całość działa poprawnie

Wcale mnie to nie dziwi. :)
Po pierwsze wyjeżdżasz poza ostatni element tablicy, więc mażesz po pamięci. To, że na Linuksie wszystko chodzi źle świadczy tylko o jego zarządcy pamięci. Twój program powinien paść od razu tak jak w Windzie. Błędem jest tworzenie tablicy o 1 element mniejszej niż liczba elementów deklarowana w parametrze. Nie byłoby to problemem gdyby warunek w pętli był taki i < il_el - 1. Równość oznacza, że próbujesz wpakować (il_el - 1) + 1 = il_el elementów do tablicy o rozmiarze il_el -1 elementów. Kompensują Ci się dwa błędy i dlatego pozornie wydaje Ci się, że na Linuksie działa.
Właśnie z takich jak ten powodów pisałem, że nie warto używać wskaźników i tablic w C.
Na dodatek masz pewnie wyciek pamięci jeżeli nie użyłeś nigdzie instrukcji delete []wskaźnik, gdzie wskaźnik jest wskaźnikiem tablicy, której pamięć przydzieliło new. Na dodatek co jest wartością zwracaną przez tab_maker? Gdzie jest instrukcje return wskaźnik? Po co w ogóle użyłeś globalnej zmiennej adres? Zamiast niej powinieneś użyć return d;.

ps. To forum nie nadaje się do wyświetlania kodu.

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

/.../
Okazało się, że nie tylko to było problemem :P
W mainie jedna z moich tablic była inicjalizowana w taki sposób:
int rozmiar;
cin >> rozmiar;
const int &rozmiar1=rozmiar;
tablica[rozmiar1];
Co wychrzaniało kod dość skutecznie (choć w sumie nie jestem pewny czemu). Zamiana tej tablicy na normalny, dynamiczny wektor rozwiązało problem definitywnie.

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

Zaczynam programować w języku C, jednak zastanawiam się nad czymś wygodniejszym od gedit. Czy polecacie jakąś konkretną aplikację, gdzie to będzie wygodniejsze, a jeśli to możliwe, to dodatkowo będzie wskazywana część błędów?

Udostępnij ten post


Link to postu
Udostępnij na innych stronach
Dnia 03.12.2009 o 15:04, Shadowtear napisał:

Zaczynam programować w języku C, jednak zastanawiam się nad czymś wygodniejszym od gedit.
Czy polecacie jakąś konkretną aplikację, gdzie to będzie wygodniejsze, a jeśli to możliwe,
to dodatkowo będzie wskazywana część błędów?


Geany. Zakładam że korzystasz z Linuksa.

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

No to dzisiaj mam 2 pytanka.
1.) Jak sprawić, by napisana aplikacja (pod Windowsa) działała w tle, tzn. nie miała żadnych okienek (chyba, że w trayu)? Jeśli to istotne, to wykorzystywana w niej będzie głównie biblioteka fstream.

2.) A to już dot. tegorocznej Olimpiady, którą, lekko powiedziawszy, skopałem :)
A więc - jak znacząco przyspieszyć wykonywanie się tego programu? Działa toto tak, że ma np. z ciągu 1 2 3 5 6
sprawdzić, czy da się uzyskać 1 2 5 poprzez usunięcie niektórych elementów. I swoją rolę spełnia. Tylko...za wolno. Niby użyłem referencji w funkcjach, o delete[] też nie zapomniałem. A mimo to jest wooolnooo.

#include <iostream>
#include <vector>
using namespace std;
int tab_maker(int il_el, vector<int>&tab1, int rozmiar){
vector<int> d(il_el);

for (int i=0; i<=il_el; i++)
{
cin >> d;
}
int polozenie_poprzedniego=0;
int licznik=0;
int sprawdzenie;
for (int a=0; a<=il_el+1; a++) // to dziala tyle razy, ile jest elementow w nowoutworzonej tablicy +1
{
if (licznik==il_el+1){sprawdzenie=1; break;}
if (a==il_el+1){sprawdzenie=0; break;}
for (int b=0; b<=rozmiar; b++){
if (polozenie_poprzedniego>rozmiar){break;}
// cout << d[a] << " jest porownywane z " << tab1[polozenie_poprzedniego] << endl;
if (d[a]==tab1[polozenie_poprzedniego]){
licznik++;
// cout << licznik << " - to jest licznik!\n";
polozenie_poprzedniego++;
break;
}
else
polozenie_poprzedniego++;
}
}
return sprawdzenie;
}

int main()
{
int m;
cin >> m;
m--;
vector<int>tab1(1000000);
tab1.resize(m);
for (int a=0; a<=m; a++){
cin >> tab1[a];
}
int ilosc;
cin >> ilosc;
ilosc--;
int il_el;
int *wyniki = new int[ilosc];
for (int a=0; a<=ilosc; a++) // generowanie i wypelnianie tablic
{
cin >> il_el;
il_el--;
wyniki[a]=tab_maker(il_el, tab1, m);

}
for (int a=0; a<=ilosc; a++)
{
if (wyniki[a]==1){cout << "TAK" << endl;}
else
cout << "NIE" << endl;
}
delete[] wyniki;

return 0;
}

Udostępnij ten post


Link to postu
Udostępnij na innych stronach
Dnia 07.12.2009 o 22:50, Sareth14 napisał:

Cześć. Zamierzam się nauczyć pisać skrypty ale potrzebuje poradnika z neta. Czy mógłby
mi ktoś znaleźć taki dla początkującego? nie znam się


A konkretnie jakie skrypty? Te w linuxowym sh? Te w windowsowym cmd? Te w PHP? Perlu? Pythonie? Ruby?
Bo trochę tam tego jest, pojęcie skrypt jest dość szerokie. Chociaż od razu mogę powiedzieć, że w internecie nie nastawiaj się na porządne poradniki. Do tego jest literatura :)

Udostępnij ten post


Link to postu
Udostępnij na innych stronach
Dnia 05.12.2009 o 15:08, ziptofaf napisał:

2.) A to już dot. tegorocznej Olimpiady, którą, lekko powiedziawszy, skopałem :)


Zgadzam się, skopałeś. I naprawdę referencje i delete[] to ostatnia rzecz, o której się myśli przy przyspieszaniu działania programu. Jak pomył do niczego to i optymalizacja kodu nic nie daje.

Bo na początku optymalizuje się ograniczając do minimum ilość istotnych operacji (w przypadku tego programu są to porównania), dopiero potem można się zastanawiać jak spowodować, żeby już gotowy kod wykonywał się szybciej. W twoim przypadku pomysł leży, a sam kod jest straszliwie chaotyczny - nie wszystko trzeba robić na intach, typ boolowski w c++ ma się dobrze. Tak bardzo mieszasz, że nawet nie chce mi się liczyć ilości wykonywanych operacji przez twój program.

A to problem liniowy - w najgorszym wypadku wykonamy tyle porównań ile elementów ma większy zbór. A sam algorytm wyszukiwania interesującego nas podzbioru bez tworzenia kontenerów dla naszych danych i operacji wczytywania to 4 linijki kodu. Teraz popatrz ile ty tego masz.

I spróbuj pomyśleć jeszcze raz. Weź papier, kartkę, i sobie to rozrysuj. Co i kiedy porównujesz i jakie dane cały czas masz dostępne.

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

/.../

Dnia 07.12.2009 o 23:32, vBoguSv napisał:

A to problem liniowy - w najgorszym wypadku wykonamy tyle porównań ile elementów ma większy zbiór.

No tak, tylko czy jest jakiś sposób na przyspieszenie tego? Teoretycznie mógłbym dodać tam takie rzeczy jak min i max wartości w danej tablicy i jeśli którykolwiek z poszukiwanych elementów je przekroczy, to wiadomo, że odpowiedź brzmi NIE, bez dalszego sprawdzania. Tylko, że to nie da mi żadnego wzrostu wydajności, jeśli po prostu zadane elementy z I tablicy zostaną np. podane w II w innej kolejności. Zapewne jest na to jakieś trywialne rozwiązanie, tylko ja go nie mogę dostrzec. Dasz może jakąś dokładniejszą podpowiedź, żeby znacząco zmniejszyć ilość przeszukiwanych danych? :)

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

Ale wydajność liniowa to bardzo dobra wydajność. I tego się już nie da przyspieszyć (w tym przypadku). W najlepszym przypadku zrobisz tyle porównań ile ma szukany ciąg - wtedy gdy szukany ciąg będzie podciągiem dużego zbioru i będzie występował w miejscu w którym zaczynasz szukać. A w najgorszym musisz przejrzeć cały duży zbiór.

Chcesz podpowiedź, proszę bardzo, ale to już prawie gotowe rozwiązanie. Podstawą jest szukany ciąg - wybierasz jego element pierwszy i szukasz jego pierwszego wystąpienia w dużym. Po czym wywalasz to co było przed i bierzesz się za kolejny element z małego.

Chyba i tak za dużo powiedziałem.

Udostępnij ten post


Link to postu
Udostępnij na innych stronach
Dnia 08.12.2009 o 00:33, vBoguSv napisał:

Chcesz podpowiedź, proszę bardzo, ale to już prawie gotowe rozwiązanie. Podstawą jest
szukany ciąg - wybierasz jego element pierwszy i szukasz jego pierwszego wystąpienia
w dużym. Po czym wywalasz to co było przed i bierzesz się za kolejny element z małego.

Eeee, ale mój kod to ma w sobie. Po to jest zmienna polozenie_poprzedniego. Czyli jak mam zbiór 3 8 5 2 7 4 i szukam w nim powiedzmy 8 2 7, to najpierw sprawdzi trójkę, potem ósemkę. Szukając kolejnego elementu zacznie od piątki, by w kolejnym odnaleźć dwójkę. I na koniec sprawdzi samą siódemkę. Fakt, że nie wywalam elementów z pierwszej tablicy, ale nie są one powtórnie sprawdzane.
Chyba, że cię nie zrozumiałem i chodzi ci o coś innego :)

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

bool funkcja (atrybuty) {
_ for (posA = 0; posA < sizeA; posA++) {
___ while (posB < sizeB && tabA[posA] != tabB[posB]) posB++;
___ posB++; }
_ return (posA == sizeA && !(posB > sizeB)); }

Legenda:
pos - pozycja w tablicy
size - rozmiar
A - tablica z naszym szukanym ciągiem
B - a tutaj tego gdzie szukamy

Masz już kod, teraz ty mi powiedz o co mi chodziło na tej podstawie. Dlaczego i jak on działa.

Udostępnij ten post


Link to postu
Udostępnij na innych stronach
Dnia 08.12.2009 o 00:45, vBoguSv napisał:

bool funkcja (atrybuty) {
_ for (posA = 0; posA < sizeA; posA++) {
___ while (posB < sizeB && tabA[posA] != tabB[posB]) posB++;
___ posB++; }
_ return (posA == sizeA && !(posB > sizeB)); }

Legenda:
pos - pozycja w tablicy
size - rozmiar
A - tablica z naszym szukanym ciągiem
B - a tutaj tego gdzie szukamy

Masz już kod, teraz ty mi powiedz o co mi chodziło na tej podstawie. Dlaczego i jak on
działa.


Pętla for, wykonująca się tyle razy, ile jest elementów w I tablicy, przy okazji zmienia też sprawdzany element tablicy I po wykonaniu tego, co dzieje się w while.
While służy właśnie do porównywania. Jak element tablicy II jest równy temu z I, to wracamy do for. A jak nie, to sprawdzamy kolejny w tablicy II. I tak do skończenia ciągu.
A na koniec return 1 jeśli TAK i 0 jeśli NIE (choć szczerze mówiąc, pierwszy raz widzę return zwracające wartość poprzez taki warunek).

Znacznie krótsze od mojego. Ale w sumie działa na podobnej zasadzie, choć ja tracę czas (choć ile konkretnie to zobaczę porównując taką wersję ze swoją o jakiejś ludzkie porze) i kod na mnóstwo nieprzydatnych elementów. Dzięki, rozjaśniłeś mi co nieco w głowie ;)

Udostępnij ten post


Link to postu
Udostępnij na innych stronach
Dnia 08.12.2009 o 01:03, ziptofaf napisał:

(choć szczerze mówiąc, pierwszy raz widzę
return zwracające wartość poprzez taki warunek).


No to jeszcze jest bardzo prosty warunek. Zdarzało się już pisać funkcje, które były jednym returnem zajmującym 2-3 linijki na kartce. ;) A przecież interpretacja tego returna jest dość czytelna: po skończeniu porównywania tablic szukany ciąg występuje w większej, jeżeli:
- przejrzałeś cały szukany ciąg [ posA == sizeA ]
- i nie brakło ci danych w zbiorze w którym szukałeś [ !(posB > sizeB) ]

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

Mam do zrobienia program ktory bedzie pokazywal wszystkie nominaly pln i euro za pomoca tablic. Pozniej na zadac pytanie w jakich srodkach chcemy otrzymac wyplate wybieramy np 1 i to jest w pln. Wpisujemy pozniej kwote a program na powiedziec ze w 1200.5 miesci sie 6*200 i 1 gr. Prosze o szybko pomoc

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

Utwórz konto lub zaloguj się, aby skomentować

Musisz być użytkownikiem, aby dodać komentarz

Utwórz konto

Zarejestruj nowe konto na forum. To jest łatwe!


Zarejestruj nowe konto

Zaloguj się

Masz już konto? Zaloguj się.


Zaloguj się
Zaloguj się, aby obserwować