Zaloguj się, aby obserwować  
UthersonL

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

1812 postów w tym temacie

Dnia 07.12.2013 o 13:54, Thrandir napisał:

Hmm... Rozumiem, że takie przekazanie całej tablicy drugi (szerzej: kolejny) raz alokowałoby
dla niej miejsce w pamięci, gdzie funkcja wrzuciłaby kopię całej tej tablicy "na własny
użytek", tak? Jeżeli tak, to rzeczywiście, przy funkcji rekurencyjnej pamięć może się
skończyć dość szybko :D


Tak, mniej więcej tak to działa. Tworzona jest po prostu kopia obiektu. A co do tego jak szybko kończy się pamięć - pracowałem na obiekcie który sam z siebie zajmował w pamięci coś koło 100 mb. Rekurencja zapchała RAM w kilka sekund, potem zabrała się za swap a potem się zawiesiła.

Tylko dobra rada - to że coś jest kopią, wcale nie oznacza że nie może przypadkiem modyfikować oryginału. Dla przykładu tablica wskaźników, nawet skopiowana, może operować na oryginalnych danych. W końcu przechowuje tylko adresy. Skopiowanie adresów nie sprawi że zaczną one prowadzić gdzie indziej.

Dnia 07.12.2013 o 13:54, Thrandir napisał:

I jak by to wyglądało w kodzie? Przyznam się, z przesłaniem całej tablicy na zasadzie
innej, niż poprzez wskaźnik jeszcze się nie spotkałem (a chętnie bym się dowiedział,
jak się to robi). W przypadku takiego wywołania wartości zapisane w pierwotnej tablicy
się nie zmienią, tak?


Kilka możliwości:
W C++:

Zamiast zwykłej tablicy użyj sobie wektora:

#include <vector>

int funkcja(vector<int> kopia)
{
}


int main()
{
vector<int> oryginal(1000);
for (int a=0; a<1000; a++)
oryginal[a]=a;

funkcja(oryginal);
}

Takie coś będzie tworzyło kopię naszego wektora (który jest tak naprawdę "nakładką" na zwykłą tablicę oferującą kilkanaście fajnych dodatków do niej).
Jeśli chcesz skorzystać z oryginału to musisz zmodyfikować int funkcja do takiej postaci:
int funkcja(vector<int> &kopia){}
Znaczek & oznacza referencję do obiektu aka "użyj oryginału". Coś jak wskaźnik tylko prostsze w implementacji. Bądź po prostu przekazujesz taki wektor właśnie poprzez wskaźnik.

Zwyczajowo też wszystkie struktury i klasy zawierające w sobie tablice będą kopiowane po wywołaniu w funkcjach.

Udostępnij ten post


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

Tylko dobra rada - to że coś jest kopią, wcale nie oznacza że nie może przypadkiem modyfikować
oryginału. Dla przykładu tablica wskaźników, nawet skopiowana, może operować na oryginalnych
danych. W końcu przechowuje tylko adresy. Skopiowanie adresów nie sprawi że zaczną one
prowadzić gdzie indziej.


Racja. Ech, BARDZO dużo jeszcze nauki przede mną, żeby tak kojarzyć wszystkie możliwe scenariusze i przeciwdziałać komplikacjom...

Dnia 07.12.2013 o 14:14, ziptofaf napisał:

Kilka możliwości:
W C++: Zamiast zwykłej tablicy użyj sobie wektora:
[...]
Takie coś będzie tworzyło kopię naszego wektora (który jest tak naprawdę "nakładką" na
zwykłą tablicę oferującą kilkanaście fajnych dodatków do niej).


Aaaaa, cwane!

Dnia 07.12.2013 o 14:14, ziptofaf napisał:

Znaczek & oznacza referencję do obiektu aka "użyj oryginału". Coś jak wskaźnik tylko
prostsze w implementacji. Bądź po prostu przekazujesz taki wektor właśnie poprzez wskaźnik.


Tak, akurat wersja z & jest bardzo intuicyjna w używaniu, dlatego chęnie po nią sięgam.

Dnia 07.12.2013 o 14:14, ziptofaf napisał:

Zwyczajowo też wszystkie struktury i klasy zawierające w sobie tablice będą kopiowane
po wywołaniu w funkcjach.


Jestem Ci bardzo wdzięczny za wyjaśnienia, dzięki Tobie kilka kwestii rozumiem teraz dużo lepiej, i czegoś się nauczyłem :)
Z niektórych rzeczy zdawałem sobie sprawę w rozumieniu: napisałem kiedyś, działało i nie sprawiało problemów, o innych nie miałem pojęcia, a teraz będę pamiętał, że tak jest zawsze i świadomie tego używał.

Udostępnij ten post


Link to postu
Udostępnij na innych stronach
Dnia 07.12.2013 o 15:07, Thrandir napisał:

Racja. Ech, BARDZO dużo jeszcze nauki przede mną, żeby tak kojarzyć wszystkie możliwe
scenariusze i przeciwdziałać komplikacjom...


Prawdę mówiąc to o czym mówisz obecnie najczęściej spada na twórców bibliotek a samemu nie musisz się nadmiernie martwić wszystkimi scenariuszami i komplikacjami jakie mogą wyniknąć poza tymi dość oczywistymi.
Zazwyczaj polega się raczej na tym że większość nowszych funkcji i klas potrafi dobrze rzucać wyjątkami co pozwala ominąć olbrzymią porcję błędów. Bloki try {} i catch {} nieraz uratowały mój kod przed wybuchem.
Jeśli jeszcze nie miałeś z nimi do czynienia bo to konstrukcja na dosyć wysokim poziomie i raczej korzysta się z tego pisząc profesjonalną aplikację a nie projekt na zaliczenie:

Wiele funkcji C++ potrafi poza typowym return 0,1, -1 które miałoby określać ich stan zwracać wyjątki.
Dla przykładu masz taki fragment kodu (wzięty akurat bezpośrednio z mojej aplikacji):
tcp::resolver resolver(io_service);
tcp::resolver::query query(hostname, "http");
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::socket socket(io_service);
boost::asio::connect(socket, endpoint_iterator);

Te komendy służą do połączenia się z serwerem WWW. Każda z nich może wywalić się w powietrze ze 100 różnych powodów. Teoretycznie możesz rozwiązywać problem po prostu sprawdzając wartość każdej z nich i jeśli jest ona taka jak oczekujesz, to przechodzisz dalej. Jeśli nie - to zwracasz np. wartość -1 w trybie natychmiastowym. Dla KAŻDEJ z tych komend z osobna. Niewygodne? O tak.

Ale możesz też po prostu wrzucić te instrukcje w blok try:

try
{
tcp::resolver resolver(io_service);
tcp::resolver::query query(hostname, "http");
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::socket socket(io_service);
boost::asio::connect(socket, endpoint_iterator);
}
A za nim umieścić block catch:

catch(std::exception& e)
{
//tu wstaw instrukcje na wypadek gdyby KTÓRAKOLWIEK z tych powyżej poszła z jakiegoś powodu nie tak.
}

W momencie gdyby którakolwiek z funkcji wywaliła się w powietrze to powiadomi nas o tym zwracając wyjątek który możemy odczytać. Wiemy też że program w obecnej formie nie pójdzie dalej więc od razu przechodzimy do bloku catch w którym jesteśmy przygotowani na taką sytuację. Jeśli wszystko jednak pójdzie dobrze to blok catch nigdy nie zostaje wywołany i program jest kontynuowany normalnie. Często nawet nie bierze się to z powodów błędu programu, realna sytuacja z mojej aplikacji:

- mamy program łączący się z serwerem i pobierający z niego jakieś dane.
- istnieje ryzyko że serwer będzie w danym momencie przeciążony bądź niedostępny z innych powodów.
- moglibyśmy ręcznie pisać funkcje które łapią takie wydarzenia. Ale wygodniej jest korzystać z wyjątków. Jeśli cokolwiek pójdzie nie tak to aplikacja walnie w nas takim wyjątkiem a my tylko wyświetlamy na ekranie jego treść np. "Server not available at the moment", "Invalid response from the server" itd. Zamiast 500 bloków if/else starcza nam jeden try i jeden catch.

Samemu pisząc funkcje i klasy też możesz z tego korzystać. Zamiast zwracać np. wartość NULL albo -1 gdy coś poszło nie tak, korzystasz wtedy z throw. I jedynym co musi robić osoba korzystająca z twojego kodu jest wsadzanie ich do bloku try.

Prosty przykład:
http://pastebin.com/WHMjZF7h
Choć normalnie używa się raczej std::exception aniżeli stringów ;P

Dnia 07.12.2013 o 15:07, Thrandir napisał:

Aaaaa, cwane!

No ja osobiście bardzo nie lubię używać zwykłych tablic i zazwyczaj będzie to albo vector albo od razu map. Wiedzą jakich są rozmiarów, można je łatwo rozszerzać a nawet usuwać z nich elementy itd. Choć faktem jest że jako obiekty nie-podstawowe trzeba pamiętać o tym że normalnie są przekazywane przez wartość.

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

Mam takie pytanko. Jak w c++ odczytać wartość konkretnej cyfry z podanej przez użytkownika liczby?
Tzn. użytkownik podaje mi np.1010110 (program ogólnie zamienia liczbę z dwójkowego na dziesiętny), a ja chcę znać wartość cyfry nr 5.
Ktoś chętny do pomocy? :)

Udostępnij ten post


Link to postu
Udostępnij na innych stronach
Dnia 08.12.2013 o 12:05, tylor2_AKA_Wylfryd napisał:

Mam takie pytanko. Jak w c++ odczytać wartość konkretnej cyfry z podanej przez użytkownika
liczby?
Tzn. użytkownik podaje mi np.1010110 (program ogólnie zamienia liczbę z dwójkowego na
dziesiętny), a ja chcę znać wartość cyfry nr 5.
Ktoś chętny do pomocy? :)


Matematycznie to dzielisz bez reszty przez 10^4 (lub podstawa systemu do potęgi cyfry do odczytania-1) a potem dzielenie modulo (%) przez podstawę systemu (w systemie dziesiętnym przez 10) - wynik to szukana cyfra. A może łatwiej odczytać po prostu konkretny znak ze stringa podanego przez uzytkownika?

Udostępnij ten post


Link to postu
Udostępnij na innych stronach
Dnia 08.12.2013 o 12:21, tylor2_AKA_Wylfryd napisał:

> A może łatwiej odczytać po prostu konkretny znak
> ze stringa podanego przez uzytkownika?
I dokładnie to chcę zrobić. Tylko nie wiem jak... :D


Pobierz długość stringa funkcją strlen i czytasz znak tekst[strlen(tekst)-(5+1)], gdzie tekst to twój string (a w zasadzie tablica znaków). Nie zapomnij o bibliotece string.h

Udostępnij ten post


Link to postu
Udostępnij na innych stronach
Dnia 08.12.2013 o 13:14, Nufiko napisał:

Pobierz długość stringa funkcją strlen i czytasz znak tekst[strlen(tekst)-(5+1)], gdzie
tekst to twój string (a w zasadzie tablica znaków). Nie zapomnij o bibliotece string.h

Rozumiem, że to co podałeś obliczy piątą cyfrę?

W każdym razie dzięki, biorę się za implementację :)

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

Pytanie nie jest może stricte związane z programowaniem, ale sądzę, że ktoś stąd będzie znał odpowiedź.

Notacja, w której bardzo często zapisujemy na komputerze różne funkcje matematyczne np. sin(x), abs(x), sqrt(x), x^2... Jak ona się nazywa? I czy znacie jakiś dobry darmowy program, w którym rozpisuje się równania z jej użyciem?

Udostępnij ten post


Link to postu
Udostępnij na innych stronach
Dnia 10.12.2013 o 10:02, Kardithron napisał:

Pytanie nie jest może stricte związane z programowaniem, ale sądzę, że ktoś stąd będzie
znał odpowiedź.

Notacja, w której bardzo często zapisujemy na komputerze różne funkcje matematyczne np.
sin(x), abs(x), sqrt(x), x^2... Jak ona się nazywa? I czy znacie jakiś dobry darmowy
program, w którym rozpisuje się równania z jej użyciem?


http://www.wolframalpha.com/

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

Korzystając z przerwy świątecznej postanowiłem napisać na laborki zaległem algorytmy. Napisałem algorytm Knutha Morrisa Pratta i niby wszystko fajnie ładnie ale nie wiem czemu zwraca mi indeksty o 2 przesunięte do tyłu. Mógłby ktoś powiedzieć mi co mam tu źle:

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <algorithm>

using namespace std;

int main()
{
char tekst[1000], wzor[100];
int p[100], t = 0;


cout << "Podaj tekst: " << endl;
cin >> tekst;
cout << "Podaj wzor: " << endl;
cin >> wzor;
int n = strlen(tekst), w = strlen(wzor);
cout << "Poczatkowy indeks wzorca: " << endl;

p[0] = 0, p[1] = 0;

for(int i = 2; i <= w; i++)
{
while((t > 0) && (wzor[t+1] != wzor))
t=p[t];
if(wzor[t+1] == wzor)
t++;
p = t;
}

int i = 1, j = 0;

while(i < n-w+1)
{
j = p[j];
while((wzor[j+1] == tekst[i + j]) && (j < w)
j++;
if(j == w)
cout << i+3 << endl;
i = i + max(1, j - p[j]);

}
}

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

Czego objawem może być cmd odmawiające przyjęcia kolejnych argumentów? Nie wyświetla formuły proszącej o kolejny argument (a pętla while się kręci), nie przechodzi dalej, nic nie robi- tylko miga znacznik, ale zostawiłem na godzinę komputer, i nie poszło nawet krok dalej. Konsolka się wiesza (zawsze po około 8 argumencie, kiedy powinna przyjmować do 13- wpisuje je do tablicy 5x5, czyli nie ma ryzyka, że wychodzi poza zakres), i nie wiem, co może być przyczyną..
Piszę program (grę) w kółko i krzyżyk na bibliotekach graficznych, no i o ile plansza 3x3 działa bez zarzutu, o tyle 5x5 odmawia współpracy po 6-8, czasem 9 ruchach. Nie zależy to od podawanych liczb, czasami nie zawiesi się w ogóle, czasami- wiesza się po trzech. Powiedziałbym, że to kwestia wiecznie się sypiącego okna graficznego, ale po jego wyłączeniu i grze bez podglądu problem pozostał.

Wiem, że wstyd z takim kodem, ale nie mogę ruszyć dalej, więc macie i się śmiejcie:

http://pastebin.com/scaNMNFW

Gdyby ktoś chciał kompilować, powinno działać w samej konsoli. I w tej wersji też się wiesza w okolicach ósmego ruchu...

P.S: Żeby bardziej poprawić humor powiem tylko, że liczenie wyznacznika metodą eliminacji gaussa to było jakieś 185 linii... :D

EDIT: GUPI TY, GUPI. Już znalazłem, losowanie pozycji przez komputer miało sztywno ustalone dzielenie (rand()%10 jest spoko przy planszy 3x3, ale nie 5x5- już zmieniam). Tak to jest, że jak się naspami posta, to rozwiązanie przyjdzie do głowy. Ale jak ktoś chce rzucić okiem, opieprzyć czy zaproponować jakąś optymalizację to będę wdzięczny :P)

Udostępnij ten post


Link to postu
Udostępnij na innych stronach
Dnia 23.12.2013 o 19:49, Thrandir napisał:

rzucić okiem, opieprzyć czy zaproponować jakąś optymalizację to będę wdzięczny :P)

Takie małe rady ogólne: fajnie jak byś się trzymał jednego języka w kodzie - mieszanka polskiego z angielskim średnio wygląda :) A w przypadku przyszłych problemów, że program powinien wykonać jakąś instrukcję, a jej nie wykonuje, polecam używanie debuggera :P Znacznie ułatwia rozwiązywanie takich zagadek, a czasami rozwiązanie problemu w kodzie bez jego użycia może być bardzo, bardzo czasochłonne (a ile nerwów się przy tym straci.. :P)

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

/.../
Jeśli chodzi o programowanie jestem raczej gorszy niż lepszy, dam jednak ''dobre'' rady które zasłyszałem.

1. Zrób główną pętlę nieskończoną w main.
2. Wyrysuj od razu plansze, zmieniaj w niej tylko wartości (ładniej i czytelniej- użytkownik wie co ma wciskać; odwrócony numlock).
3. Zamień 1 i 2 na X i O
4. Menu zrób na switch, a nie na pętlach. Dużo tam tego powsadzałeś. :P
5. Nie ma sensu wyważać otwartych drzwi, użyj http://pl.wikipedia.org/wiki/Algorytm_min-max
6. Obsługa błędów, zobacz co się dzieje jeśli zamiast cyfry wpiszesz ciąg znaków.


Od razu mówię, nie jestem specjalistą i to są tylko i wyłącznie dobre rady z dobrego serca, wiem, że mnie też wiele brakuje do bycia dobrym koderem.

Udostępnij ten post


Link to postu
Udostępnij na innych stronach
Dnia 23.12.2013 o 22:36, Daronn_Darker napisał:

1. Zrób główną pętlę nieskończoną w main.


Mniej-więcej to robi pętla mówiąca "Wciśnij 1 aby zagrać jeszcze raz"

Dnia 23.12.2013 o 22:36, Daronn_Darker napisał:

2. Wyrysuj od razu plansze, zmieniaj w niej tylko wartości (ładniej i czytelniej- użytkownik
wie co ma wciskać; odwrócony numlock).
3. Zamień 1 i 2 na X i O


Plansza jest rysowana w oknie graficznym, na potrzeby szukania błędu przekształciłem kod jako wyrzucający kolejne macierze planszy, normalnie wygląda to tak:

http://i43.tinypic.com/2ekm2r6.jpg

Z dokładnością do brakującej numeracji pól, która również będzie generowana (żeby wiadomo było, co wpisać, aby postawić X tam, gdzie się chce- przy planszy 5x5 jest to istotne).

Dnia 23.12.2013 o 22:36, Daronn_Darker napisał:

4. Menu zrób na switch, a nie na pętlach. Dużo tam tego powsadzałeś. :P


Szczerze powiem, menu praktycznie nie istnieje :P Które konkretniej pętle mógłbym jeszcze przekształcić na switch?

Dnia 23.12.2013 o 22:36, Daronn_Darker napisał:

5. Nie ma sensu wyważać otwartych drzwi, użyj http://pl.wikipedia.org/wiki/Algorytm_min-max


Ogarnę, acz po pierwszym przeczytaniu tekstu (który niewątpliwie mi się przyda w ogólności) nie rozumiem, do której konkretniej części powinienem to zastosować.

Dnia 23.12.2013 o 22:36, Daronn_Darker napisał:

6. Obsługa błędów, zobacz co się dzieje jeśli zamiast cyfry wpiszesz ciąg znaków.


Wywala program (spamuje literkami), i nie wiem, co z tym zrobić :D

Dnia 23.12.2013 o 22:36, Daronn_Darker napisał:

Od razu mówię, nie jestem specjalistą i to są tylko i wyłącznie dobre rady z dobrego
serca, wiem, że mnie też wiele brakuje do bycia dobrym koderem.


Bardzo za nie dziękuję, po prostu wdzięczny byłbym za doprecyzowanie tego, co masz na myśli (nie rozumiem, czego konkretnie tyczą się punkty 4 i 5 :D).

P.S: Tak, jestem ograniczony do względnie czystego C oraz tej właśnie, bardzo marnej biblioteki graficznej- praca na zaliczenie, w wersji pierwotnej była zresztą jeszcze mniej ambitna, ale trochę całość podrasowałem, coby mieć radość przy kombinowaniu i sklecaniu kodu...

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

/.../
@4. Masz ''za dużo'' pętli w programie, ja czytając kod co chwile się gubiłem. Przekształć te if na switch, w Twoim menu.

@5. Skoro grasz z komputerem, to najlepiej jest użyć jakiegoś algorytmu by komputer mógł wygrać :P, taki algorytm do sztucznej inteligencji to właśnie np. minimax(chyba najprostszy). Nawet jeśli nie użyjesz go tutaj, przydać się na 100% przyda Ci kiedyś.

BTW. Nie wiem czy ja, czy mój mózg, ale może mi ktoś wyjaśnić czy na stronie qt sa tylko tutoriale do QML?

Udostępnij ten post


Link to postu
Udostępnij na innych stronach
Dnia 23.12.2013 o 23:48, Daronn_Darker napisał:

/.../
@4. Masz ''za dużo'' pętli w programie, ja czytając kod co chwile się gubiłem. Przekształć
te if na switch, w Twoim menu.


Ok, pokombinuję, bo faktem jest, czyta się to słabo...

Dnia 23.12.2013 o 23:48, Daronn_Darker napisał:

@5. Skoro grasz z komputerem, to najlepiej jest użyć jakiegoś algorytmu by komputer mógł
wygrać :P, taki algorytm do sztucznej inteligencji to właśnie np. minimax(chyba najprostszy).
Nawet jeśli nie użyjesz go tutaj, przydać się na 100% przyda Ci kiedyś.


Aaa, w tym sensie :D Tak, to to właśnie robię (od tego jest poziom HARD, który w momencie szukania błędu nie był nawet jeszcze zaczęty), acz póki co kombinuję z własnym algorytmem optymalizującym działanie gracza komputerowego. Dzięki za link, bardzo się przyda :)

Udostępnij ten post


Link to postu
Udostępnij na innych stronach
Dnia 23.12.2013 o 23:48, Daronn_Darker napisał:

@4. Masz ''za dużo'' pętli w programie, ja czytając kod co chwile się gubiłem. Przekształć
te if na switch, w Twoim menu.


"If" to nie jest pętla, tylko instrukcja warunkowa. Dobrze sformatowana jest tak samo czytelna jak jak switch, a daje większe możliwości.

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ć