programowanie w C - bardzo ogólne pytanie o filozofi

witam bardzo bardzo hobbisticznie zajmuję się arduino. w wolnych chwilach, żeby synowi zaszczepić.... Nie. Żeby się nie bał elektroniki. Wpadłem na pomysł aby pralkę w której umarła elektronika, naprawić za pomocą arduino. Tyle ze ja pokolenie temu programowałem zx spectrum, więc jestem skażony na całe życie Czy w basicu czy w C++, zacząłbym od napisania sekcji, takich jak pranie, czyli: spawdzenie czy jest woda, czy klapka zamknięta i obracanie bębnem w prawo i lewo, Wirowanie, czyli znowu - klapa, woda i dawaj z obracaniem itd. pralkę zaopatrzyłbym w 3 pokrętła. czas prania, szybkość wirowania i temperatura. użytkownik ustawiałby nimi wartość zmiennych czas, temp, obr. no i w basicu, każda z sekcji zaczynałby się w konkretnej lini. pranie 100, płukanie 200, wirowanie 300. sam program wykonawczy wyglądałby ( w uproszczeniu ) tak: go to 100 (pranie) go to 100 (pranie) go go 100 (pranie) go to 200 (płukanie) go to 300 (wirowanie) nie chcąc komplikować emaila, użyłem 3 zadań, ale ze wzrostem ich liczby, program w bascu, tylko lekko urośnie. w C++ - nie mam pojęcia jak to _dobrze_ zrobić. precyzując - zrobię, program wychodzi 2 razy dłuższy, i to na zasadzie, rób _wszystko_ po kolei (bo nie mogę skakać po numerach lini), ale jeśli jakiś tam parametr był już zrobiony(wybrany), to pomiń.... (np płukanie). tak, da się, ale program robi się znacznie dłuzszy, coraz więcej zmiennych, i tabun if-ów. no nie wierzę że nieda się tego w C++ zrobić prościej.

Czy moglibyście mi pi razy oko wyjasnić jak to sie w C robi? Tyle ze nie mogą być to osobne programy zapisane na dysku (do wczytywania w miarę trwania prania), bo to trzeba na raz wgrać do arduino.

ToMasz

PS PRalki jeszcze nie tknąłem.

Reply to
ToMasz
Loading thread data ...

W dniu 2017-10-23 o 23:07, ToMasz pisze:

Kupić zestaw czujników + wyświetlacz i się bawić z synem.

Wpadłem na

Zły pomysł, tam jest sieć, i do zabawy się to nie nadaje, wpierw trzeba wymyśleć międzymordzie pomiędzy czujnikami, zaworami, silnikiem a avrduino. To nie bułka z masłem.

W C są funkcje, nie ma numerowania lini bo funkcje identyfikuje sie po nazwie a nie numerze linii w której występuje. Poczytaj razem z synem kurs arduino, tam masz to wyjaśnione.

I dobrze, jeszcze sobie lub dziecku krzywdę zrobisz.

Reply to
Janusz

W C/C++ możesz z grubsza programować tak, jak to się robiło w Basicu. Służą do tego etykiety (słowo zakończone dwukropkiem) oraz instrukcja goto. Tylko moim zdaniem nie ma to większego sensu - instrukcja ta przydaje się sporadycznie (choć w pewnych sytuacjach faktycznie się przydaje), a jej nadużywanie drastycznie zmniejsza czytelność kodu. Są tacy, których zdaniem nie powinno się jej używać w ogóle.

Programowanie strukturalne albo obiektowe jest dużo bardziej naturalnym rozwiązaniem od tego, z czym ma się do czynienia w Basicu albo asemblerze. Dlatego warto jak najszybciej pozbyć się starych przyzwyczajeń.

Reply to
Atlantis

W dniu 2017-10-24 o 09:31, Atlantis pisze:

Nigdy nie zdarzyło mi się mieć potrzeby użycia w C instrukcji goto, ba, nawet jakby mnie ktoś poprosił o wymienienie wszystkich instrukcji dostępnych w C to chyba bym sobie o niej nie przypomniał, a używam (sporadycznie i nie do mikrokontrolerów) C gdzieś tak od 1986r.

Tak się zastanawiam do czego ona mogła by być przydatna i nie bardzo potrafię wymyślić jakiś przykład generujący realną taką potrzebę. A jeśli już w ogóle to chyba tylko wewnątrz jednej funkcji do jakiegoś rozwikłania czegoś co w przeciwnym wypadku wymagało by albo dwukrotnego napisania kilku linijek programu, albo ujęcia ich w kolejną wywoływaną funkcję. Na pewno wybrałbym jedno z tamtych rozwiązań, a nie goto, choćby dlatego, że nie pamiętam o jego istnieniu. P.G.

Reply to
Piotr Gałka

Użytkownik "ToMasz" napisał w wiadomości grup dyskusyjnych:osllnb$psp$ snipped-for-privacy@dont-email.me...

Na tym poziomie zaawansowania ... kup nowa pralke :-) Ale na starej mozesz pocwiczyc - przyda sie do nowej, jak sie zepsuje :-)

A tu choroba "przerwania" przychodza - zona chce program zmienic, albo zapomniany ciuch dorzucic.

go sub chyba ... tak, zeby mogl wrocic.

Ilu programistow, tyle metod.

J>

Reply to
J.F.

Użytkownik "Piotr Gałka" snipped-for-privacy@cutthismicromade.pl napisał w wiadomości news:osmsrd$mk1$1$ snipped-for-privacy@news.chmurka.net...

Ja w basicu też mniej-więcej tak. Przyznaję, używałem, w różnych dialektach. Głównie w sytuacji, gdy np. finalizowałem program i np. trzeba było przeskoczyć baterię podprogramów (tak, jak najbardziej daje sie programować strukturalnie, obiektowo? Przyznam, że nie wiem, musiałbym poznać, co to), a upraszczało to program... Albo z lenistwa :)

Na szybko, z numerami linii, trochę lenistwa (jak np. coś się rzeźbiło ad-hoc, nie szkoda róż, gdy płonie las, jak szkoda było czasu na grzeczności)

10 coś-tam 20 gdzieś tam 25 IF n=7 GOTO 50 30 GOSUB 100: REM drapanie po tyłku 40 GOSUB 200: REM klepanie po ramieniu 50 END: REM kończymy program, można zastosować, robiło się IF n=7 THEN END 100 podrap mnie: RETURN 200 poklep mnie: RETURN

Czasami szybciej było tak "na chama", niż tworzyć dodatkowo zestaw procedur. Poza tym, zajmowało mniej pamięci, niewiele, czasem było to decydujące, jak program był na styk w pamięci, co w małych komputerkach było całkiem częste.

Różnie, często z lenistwa, ale też często z braku (poza GOSUB/GO SUB - zależnie od dialektu) mechanizmu wspierającego strukturalność w wielu dialektach BASICa. Pierwsze możliwości trafiłem w QBASIC M$, gdzie zresztą linie programu są już w rzeczywistości etykietami i tak przez interpreter uważane. Gdzie jawnie można już było używać etykiet, już chyba od GWBASICa była też rozszerzona instrukcja IF: (nie pomnę teraz dokładnej składni, ale mniej więcej...)

IF n=7 podrap mnie po głowie powiedz coś miłego mozna było zagnieżdżać pętle ENDIF

Jeszcze pętle WHILE-WEND, co dialekt, to inaczej.

No, gdybym od początku tak mógł..., zresztą nawet wszelkie pisemka pyszczyły, aby unikać goto, żeby działać strukturalnie, dzięki czemu np. w razie zmiany jakiegoś komponentu przegrzebać trzeba będzie tylko jego podprogram, zamiast rzeźbić ponownie całość, taka konstrukcja modułowa. Zresztą, dla zabawy bawiłem się (tautologia, wiem), w programowanie strukturalne używając tylko goto, bez gosub i innych procedur definiowanych.

Dzisiaj... chyba już mi się nie bardzo chce, bo się nie bawię... Sporadycznie...

Reply to
HF5BS

W dniu 2017-10-24 o 10:15, Piotr Gałka pisze:

Znalazłby się, np wyjście z podwójnej pętli, breakiem wyjdziesz tyle że pętlę wyżej gdzie musisz testować warunek dalszego wyjścia, jak widzisz zaciemnia się kod i robi się to mało eleganckie.

Reply to
Janusz

W dniu 2017-10-23 o 23:07, ToMasz pisze:

W C zrobisz np. tak:

int obroty(int kierunek,int czas) { // tu sterowanie silnikiem i odmierzenie czasu }

int pranie(int cykli) { int i; int err;

for(i=0;i<cykli;i++) { err=obroty(0,5); // w lewo, przez 5 sekund if(err!=0)return err; err=obroty(1,5); // w prawo, przez 5 sekund if(err!=0)return err; } return 0; // oznacza że się udało bez błędów }

//podobnie int plukanie(int cykli) {

}

int wirowanie(int czas, int predkosc) {

}

//i całość

void main() { int err;

err=wlewanie_wody(); if(err==0)err=pranie(50); if(err==0)err=plukanie(5); if(err==0)err=wirowanie(20,1000); if(err!=0)mrugaj_czerwownym_LEDem_w_nieskonczonosc(); zapal_LED_koniec_prania(); }

Użyłem int jako err bo ogólnie błędom można nadać różne numery i je rozróżniać. Ale jak jest tylko zero/jedynkowo to czytelniej byłoby wszędzie gdzie jest err zamiast int użyć bool.

Ja zaczynałem się uczyć C od książki Kernighan, Ritche "Język C", ale to było wieki temu. Nie mam pojęcia czy teraz jest coś lepszego aby zacząć od podstaw. Ale na pewno warto - choćby dla swojego samorozwoju.

Z tym, że ja uważam, że nie koniecznie trzeba zaprzęgać C do hardawre'u. Równie dobrze można korzystać z komputera samego w sobie.

Zadanie 1 ode mnie:

1.Napisz program do wypisywania na ekranie kolejnych liczb pierwszych (np. do 100, a jak już będzie działał to zmień zakres na 1000). 2.Otocz go pomiarem czasu wykonania - czyli jak kończy to wypisuje ile mu to zajęło. 3.Rozdziel proces wyliczania od procesu wypisywania liczb pierwszych (czyli wyniki zbieraj w buforze i potem wypisuj z bufora). 4.Zamiast wypisywać liczby pierwsze wypisz tylko ich liczbę (wiesz ile zebrałeś ich w buforze). Możesz zwiększyć zakres poszukiwania - może do 10000. 5.Zastanów się co można zmienić w algorytmie aby program liczył szybciej

- masz gotowe narzędzie do sprawdzenia czy pomysł jest dobry, czy zły, a wypisywanie liczby znalezionych liczb ma wykryć sytuacje, gdyby modyfikacja algorytmu coś w nim zepsuła i jednocześnie nie zajmuje czasu wypisywaniem wszystkich liczb, bo obsługa ekranu jest czasochłonna

Ewentualne zadanie 2 (moim zdaniem trudniejsze): Mieliśmy kiedyś taką grę "samotnik" (jest pewnie wiele typów). Trójkąt - w dolnej linii 5 dziurek, w następnej 4 itd aż na górze jedna. Wkłada się w to pionki zostawiając jedną dziurkę wolną i następnie zbija je jak w warcabach. Celem jest aby został tylko jeden pionek.

Mój, wtedy chyba 7 letni, syn się bardzo irytował, że to nigdy nie da się zrobić i pytał, czy ja umiem. Powiedziałem mu, że ja takie problemy rozwiązuję inaczej. Usiedliśmy przy komputerze i po około 2h miałem program (w międzyczasie tłumaczyłem dziecku mniej więcej jak zapisuję to zadanie (obrazkowo na papierze, a nie w kodzie)), który dla każdego stanu początkowego wyszukiwał wszystkie sekwencje prowadzące do sukcesu. Mój program składał się z 13-tu zagłębionych pętli for(). Każda pętla wykonywała jeden ruch i wołała kolejną (chyba, że ruch już nie był możliwy). Jak dochodziło do ostatniej i ona mogła wykonać ruch to oznaczało sukces. Jak już to miałem to użyłem tej procedury do policzenia ile sekwencji kończy się sukcesem w każdej z 4 sytuacji początkowych (inne są symetryczne) z tego wyszło, z jakiej zaczynać aby mieć największą szansę. A potem dla każdej sytuacji wydrukowałem po 10 sekwencji prowadzących do celu i on już sam je sobie "w realu" przećwiczył i bardzo mu się podobało, że nareszcie ta wkurzająca gra została pokonana. P.G.

Reply to
Piotr Gałka

W dniu 2017-10-24 o 10:15, Piotr Gałka pisze:

Mam podobny staż i też nie używam goto, ale jedyny raz to zrobiłem w pewnym konkretnym przypadku. Musiałem zaimplementować algorytm liczenia pierwiastków zespolonych wielomianu dowolnego stopnia. W jakiejś książce znalazłem gotową procedurę w Fortranie. Kod był strasznie pokręcony i miał powtykane goto w wielu różnych miejscach, np. w ten sposób było zrobione wyjście z pętli, ale i wskoczenie do pętli w inne miejsce po spełnieniu jakiegoś warunku na zewnątrz. Próbowałem to przerobić na jakąś czytelniejszą postać, ale w końcu się poddałem i mechanicznie przepisałem na C, wraz ze wszystkimi goto. Poszło od pierwszego razu, więc nie chciało mi się już później przy tym grzebać :)

Reply to
ajt

W dniu 2017-10-24 o 10:56, HF5BS pisze:

To jest wypowiedź w kontekście mojego poprzedniego zdania - czyli piszę o języku C.

A Ty odpowiadasz jakbym napisał, że w BASICU nie używałem GOTO. Akurat w BASICU (na Commodore 64) używałem. P.G.

Reply to
Piotr Gałka

W dniu 2017-10-24 o 11:22, Janusz pisze:

Kiedyś przetestowałem break;break; i OIDP zadziałało dobrze, ale nie byłem pewien, czy to przypadek, czy cecha języka więc dołożyłem bool który służył tylko do tego aby zewnętrza pętla wiedziała, że wewnętrzna każe wyjść. Potem chyba zastąpiłem wewnętrzną przez osobną funkcję inline i wydaje mi się to lepszym/czytelniejszym rozwiązaniem niż goto.

Kilka lat temu kupiłem sobie ostatnią książkę Stroustrupa o C++. Nie przebrnąłem przez całą. Utkwiło mi w pamięci, że według niego jak funkcja ma więcej jak 7 linijek to znaczy, że program jest źle napisany. Jest to wspomniane gdzieś gdzie przykłady są już dla mnie prawie nie zrozumiałe. Może kiedyś.... P.G.

Reply to
Piotr Gałka

W dniu 2017-10-24 o 11:39, ajt pisze:

O takiej potrzebie nie pomyślałem :)

Jakieś gotowe algorytmy (odwracanie macierzy i inne) przepisywałem kiedyś dawno z ruskiego "Sprawocznika Algoritmow na jazyku ?" to chyba był Algol więc OIDP żadnych goto nie było. Przepisałem też kiedyś FFT (nie wiem skąd) do Basica - na Commodore-64 zrobiłem próbkowanie 3s mowy do RAMu i potem malowanie pseudo 3D wykresu zmiany widma w funkcji czasu. Mój profesor miał nadzieję, że zrobię komputerowe rozumienie mowy, ale przecenił moje możliwości :) Wtedy jeszcze u nas na Politechnice Gdańskiej nie było ani jednego IBM-PC. P.G.

Reply to
Piotr Gałka

Raczej przypadek... Albo jakieś dziwne zachowanie kompilatora którego użyłeś. ISO-9899-1990 mówi: "6.6.6.3: A break statement terminates execution of the smallest enclosion switch or iteration statement."

Dlatego więc drugie 'break' w przykładzie który podajesz jest (a przynajmniej powinno być) martwym kodem.

Prosty test:

int main(void) { for (;;) { for (;;) { break; break; } } return(0); }

Powyższy program (po kompilacji i uruchomieniu) nigdy się nie kończy. A mój gcc optymalizuje go to tej postaci :)

.L2: nop jmp .L2

GOTO jest faktycznie dość niepopularne w C, i sam mało kiedy mam potrzebę go użyć, jednak nie zgadzam się z fanatykami którzy twierdzą iż goto to jakieś największe zło i należy je usunąć z języka. Jedyna sytuacja którą pamiętam to gdy potrzebowałem wyjść z switch() zagnieżdżonego w jednej lub dwóch pętlach. Jedno 'goto' pozwoliło domknąć projekt, zamiast refaktoryzować wszystko kilka dodatkowych dni. Niby anegdota, ale fajnie mieć pod ręką takie goto 'w razie czego'.

Też czytałem takie opinie, ale chyba z innego źródła, bo Stroustrupa przeczytałem tylko wstęp i miałem dość :) Ta reguła siedmiu linijek to jakiś wymysł nowego pokolenia... Zdarzało mi się miewać takich wśród moich pracowników. Młodym się chyba nudzi i wymyślają sobie różne zabawy. A jak trzeba coś konkretnego zrobić to sięgają po zewnętrzne biblioteki by rozwiązać nawet relatywnie proste sprawy, "bo po co wymyślać na nowo", a potem projekt nie da się skompilować bo wymaga miliona zależności, których połowa już nie istnieje lub zmieniła API. Życie.

Mateusz

Reply to
Mateusz Viste

Użytkownik "Piotr Gałka" napisał w wiadomości grup dyskusyjnych:osmsrd$mk1$1$ snipped-for-privacy@news.chmurka.net...

Nie uzywasz, bo jestes "dobrze nauczony", to nie pamietasz. Pomysl lepiej ile razy kombinowales, gdy jedno goto zalatwiloby sprawe,

To tez.

jak podano - wyjscie z zagniezdzonych petli. A nawet szukanie czegos w jednej petli - znalazles lub nie znales. Break i sprawdzac po liczniku petli czy dotarles do konca ? Czy flage pomocnicza sobie zalozyc ?

A teraz wpadlem w jakies bazy danych i mozg mi sie czasem lasuje od logiki. wyszukac rekord. Jak jest - to poprawic. Jak sa dwa to blad zglosic, albo co gorsza poprosic o wybranie uzytkownika. Jak nie ma - wyszukac po innym kryterium. I znow - poprawic lub dopytac. A jak nie ma, to w koncu zalozyc. A to tylko najprostszy przypadek, bez szykan.

Inna sprawa, ze jakbym tak zaczal mieszac za pomoca goto, to pewnie tez bym sie pogubil :-)

J.

Reply to
J.F.

W dniu 2017-10-24 o 12:30, Mateusz Viste pisze:

Sprawdziłem. U mnie (Builder 5) też się zapętla. Pomyślałem, że może ze switch wewnątrz for tak mi się udało wyjść, ale też nie.

Dziwi mnie bo moje OIDP wydawało mi się prawie pewne, a nie używam innych kompilatorów niż Builder.

Ja bardzo mało czasu programuję - średnio będzie 2..3 tygodnie w roku. Nigdy nie próbowałem użyć żadnej zewnętrznej (znaczy nie zintegrowanej fabrycznie z Builderem) biblioteki. Szczerze mówiąc nie wiedziałbym jak się w ogóle do tego zabrać :) Jak z 10 lat temu potrzebowałem DES, AES, SHA, CMAC, HMAC to wziąłem dokumenty NIST i sobie je napisałem (przy okazji popełniając błąd, który nie został wykryty przez ich wektory testowe :) ). P.G.

Reply to
Piotr Gałka

Jeżeli pralka do zabawy to:

formatting link
Włodek

Reply to
invalid unparseable

A mnie się zdarza stosunkowo często, choć przypadki użycia są jedynie dwa:

  1. Opuszczanie wielokrotnie zagnieżdżonych pętli.
  2. Przekazywanie sterowania do wspólnego kodu obsługi błędu dla danej sytuacji:

if (dobrze) {

// to dobrze } else {

lbl_zle:

// bardzo zle }

if (albo_jednak_zle) {

goto lbl_zle; }

Dokładnie o to chodzi. Goto potrafi znacznie *podnieść* czytelność, tylko trzeba go używać z głową. To przydatna konstrukcja, niepotrzebnie obrosła mitami.

Pozdrawiam, Piotr

Reply to
Piotr Wyderski

W dniu 2017-10-24 o 12:58, J.F. pisze:

Czasem kombinowałem, ale na prawdę nie pamiętając w ogóle o istnieniu goto nigdy nie miałem myśli "jedno goto załatwiloby sprawę" dlatego nie mam pojęcia czy tak było w tych przypadkach gdy kombinowałem.

Jak dopada mnie taki przypadek to robię podfunkcję z której w wielu miejscach wychodzę przez return - w sumie to podobne do goto i możliwe że też jest 'be'.

Jak użyć goto tak jak wyżej opisany return to pewnie na czytelności wiele nie traci, ale jak byłoby w funkcji kilka etykiet i gdzieś tam skoki do nich - niektóre do przodu, niektóre do tyłu to chyba bym zwariował próbując zrozumieć. P.G.

Reply to
Piotr Gałka

Przypadek, błąd w kompilatorze najprawdopodobniej. Sterowanie nie ma prawa dojść do drugiego goto. Poza tym spróbuj tak opuścić switcha zawartego w petli. :-)

Czyli klasycznie zacząłeś wbijać gwoździe kombinerkami, bo Dijkstra chlapnął, że goto jest złe.

Jeśli możesz poprawić strukturę programu w ten sposób, to zawsze warto, nie tylko z powodu goto. Natomiast jeśli nie możesz, to... przyznaj, że nie możesz i użyj goto, a nie kombinuj. Ta konstrukcja jest w języku

*celowo*.

Nie pierwsza to i nie ostatnia głupota, a papier w mordę nie da...

Pozdrawiam, Piotr

Reply to
Piotr Wyderski

Użytkownik "Piotr Gałka" napisał w wiadomości grup dyskusyjnych:osn8vc$r5s$1$ snipped-for-privacy@news.chmurka.net... W dniu 2017-10-24 o 12:58, J.F. pisze:

W assemblerze mi sie nie mylilo :-)

IMO - to sie stad wzielo, i moze troche z numerowania linii jak w Basicu i moze kart jak w czasach Fortranu.

Bardzo poczatkujacy programisci w basicu rozwijajac program bardzo szybko tworza takie dzikie struktury z wieloma zupelnie niepotrzebnymi skokami, a potem sami sie w tym gubia. Wiec Wirth zabronil skokow i mial spokoj (choc w Pascalu goto jak najbardziej jest, za to nie ma break i continue).

Byc moze ma to jeszcze cos wspolnego z dowodzeniem poprawnosci programow - w tak "dzikiej" strukturze trudno dowod przeprowadzic.

J.

Reply to
J.F.

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.