Kod w C do sprawdzenia

Kod w C do sprawdzenia
0

Witam,

Mam problem z kodem w C. Mam za zadanie przeanalizowac kod zalaczony ponizej pod katem bledow, niespojnosci, zlych praktyk i znalezc najgorszy blad i zasugerowac jego poprawe.

Nie oczekuje, ze ktos rozwiaze za mnie zadanie, NIE ale PROSZE o to czy ktos z doswiadczonych programistow moze spedzic 5 minut i zerknac na ten kod i powiedzic czy dostrzega jakeis bledy w C ? Ja usiadlem nad tym i nie moge nic znalezc, albo za malo wiem albo jestem slepy ...

czas mi ucieka, bo mam zadanie oddac na poniedzialek i postanowilem zasiegnac porady na forum. czy jest ktos w stanie pomoc ?

http://www.menie.org/georges/embedded/xmodem.html

0

ok, domyslam sie, ze uzycie goto jest bledem i ze nie kazdy case w switch'u nie ma break'a.

Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Wrocław
  • Postów:13042
3

domyslam sie, ze uzycie goto jest bledem
Nie jest to błąd, tylko zła praktyka.

nie kazdy case w switch'u nie ma break'a
Tzw. fallthrough także nie jest błędem, a celowym działaniem. Na przykład jeśli chcesz, aby kod wykonywał się dla liczb 2, 3 oraz 5, to robisz:

Kopiuj
switch (liczba) {
  case 2:
  case 3:
  case 5:
    cośtam;
  break;

Ewentualnie autor wykorzystuje goto, więc ten brejk tak czy owak byłby zbędny.

Z tego co odkryłem:

  1. Autor nigdzie nie dostał olśnienia, że istnieje typ size_t, a szkoda. To nie jest błąd per se, ale może być błędogenne, a już na pewno namawia do przemyśleń dlaczego autor przewidział odnoszenie się do tablicy po ujemnym indeksie, po to tylko, aby się okazało, że jednak nie przewidział ;p
  2. To pewnie kwestia wieku tego kodu, natomiast już nie korzysta się z modyfikatora register (por. register int count = destsz - len;), ponieważ kompilatory i tak lepiej wiedzą, co gdzie wsadzić ;-)
  3. Funkcje xmodemReceive oraz xmodemTransmit są zdecydowanie za długie i mają zbyt duży poziom zagnieżdżeń.
  4. Nie rozumiem, dlaczego autor raz robi case 'C':, a potem case NAK: - tzn. dlaczego raz na pałę wstawia literał, a za drugim razem wykorzystuje zdefiniowane wyżej NAK. Ja wszystko oparłbym o stałe/define'y, aby nie mieszać.
  5. for (i = 0; i < (bufsz+(crc?1:0)+3); ++i) { robi mi się gorąco gdy patrzę na ten warunek - bynajmniej nie z podniecenia.
  6. Kody błędów są liczbowe, wpisane na chama prosto w kod (np. return (c == ACK)?len:-5;) - tak się nie robi. return (c == AKC) ? len : ERR_NO_ACK_RECEIVED;, z uprzednią definicją #define ERR_NO_ACK_RECEIVED -5 (nazwa przykładowa) jest znacznie czytelniejsze.

To tak pobieżnie - doczepić można by się tutaj praktycznie co drugiej linijki.


edytowany 7x, ostatnio: Patryk27
0X
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 8 lat
  • Postów:15
0

Czesc Patryk,

Dziekuje za szybka odpowiedz.

for (i = 0; i < (bufsz+(crc?1:0)+3); ++i) ... w sensie, ze '(bufsz+(crc?1:0)+3)' powinno byc zdefiniowane wczesniej poza funkcja ?

Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Wrocław
  • Postów:13042
1

Choćby i było zdefiniowane wcześniej.
Cokolwiek, aby ten brzydki warunek nie był taki... brzydki.


MarekR22
Moderator C/C++
  • Rejestracja:około 17 lat
  • Ostatnio:2 minuty
1

Jak robię review, takiego kodu to automatem pierwszy zarzut: funkcje są za długie, podziel to najmniejsze.
Czemu? Bo przy takich monolitach nie da się zrobić uczciwego code review, bo sprowadzi się on do poprawek literówek i standardów formatowania kodu, a samej logiki się nie zrozumie (a z architekturą będzie ciężko).


Jeśli chcesz pomocy, NIE pisz na priva, ale zadaj dobre pytanie na forum.
edytowany 2x, ostatnio: MarekR22
0X
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 8 lat
  • Postów:15
0

Dzieki Marek,

a co myslisz o braku komentarzy ? Czy jest to zla praktyka ?

edytowany 1x, ostatnio: 0xpuzzle
kaczus
  • Rejestracja:około 10 lat
  • Ostatnio:4 minuty
  • Lokalizacja:Łódź
  • Postów:1402
2

Komentarze tylko tam, gdzie rzeczywiście sa niezbędne, ew w nagłówkach, zeby ładnie tworzyła się dokumentacja automatyczna. Ogólnie, jeśli nie robisz jakiś "sztuczek" albo innych niekonwencjonalnych rzeczy to kod ma byc czytelny na tyle, aby dokumentacja nie była potrzebna.
dodano:
A ew jeszcze robie sobie rzeczy typu [todo] - ale to pewnie ze wzgledu na wiek, aby nie zapomniec, ze piszac i testujac, jeszcze czegos nie zrobilem.


Ogólnie na prace domowe mam stawki zaporowe. Czasem coś o programowaniu znajdzie się na mojej stronie
edytowany 1x, ostatnio: kaczus
0

czy ktos moglby zamiescic jeszcze jakies uwagi / spostrzezenia co do zamieszczonego kodu ? dzieki

_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:2 miesiące
0

To raczej wieloetapowe, poczytaj co napisał @MarekR22 tu: http://4programmers.net/Forum/1209978
Jak poprawisz to co już wiesz to wklej kod, wtedy będzie nieco jaśniej.


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
0

a czy samo uzycie funckji for w takiej postaci jest bledem ?

Kopiuj
for(;;)
0
Pijany Krawiec napisał(a):

a czy samo uzycie funckji for w takiej postaci jest bledem ?

Kopiuj
for(;;)

znaczy sie rozumiem, ze nie ma warunkow i funckja bedzie dzialac w nieskonczonosc, chybaze mam break w funckji.

_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:2 miesiące
1

Jak rozumiesz to czemu pytasz?


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Wrocław
  • Postów:13042
1
  1. for nie jest funkcją.
  2. A pisanie for (;;) nie jest błędem - jedni wolą while (1), a inni for (;;). Inna sprawa, że nieskończona pętla stanowi niezbyt zalecaną konstrukcję, ponieważ nie jest jasne, kiedy kod się przerywa (wiadomo, że po break, ale warunek nie jest ukazany wprost). Podobna sprawa jak w przypadku goto.

edytowany 1x, ostatnio: Patryk27
Zobacz pozostałe 2 komentarze
Endrju
A co złego w C? (Od 17 lat w C jest true)
Endrju
#include &lt;stdbool.h&gt; jakby zapomniałeś.
_13th_Dragon
Trochę nie to samo, aczkolwiek nigdy nie sprawdzałem jak to wygląda po kompilacji.
J0
Nie prościej <code>#define true 1</code>, wy to sobie zawsze utrudniacie robotę.
0

czesc, wrzucilem kod w splinta i lece linijka po linijce i zastanawiam sie nad:

Kopiuj
if(crc)  
<- Blad z tego wzgledu, ze crc jest zdeklarowane wczesniej jako int a warunek musi by bool
Kopiuj
unsigned short tcrc = (buf[sz]<<8)+buf[sz+1];
<- to bym rozbil na dwie linie kodu i najpierw zdeklarowal <code class="c">(buf[sz]<<8)+buf[sz+1]
Kopiuj
```c
crc16_ccitt 

<-- jest niezdeklarowane

Kopiuj
unsigned short tcrc = (buf[sz]<<8)+buf[sz+1];

<-- czy to jest bledem ze tcrc jest short a po prawej wynik jest int ?
unsigned char cks = 0; <- czy takie cos jest bledem ? czy cks powinno bys zdeklarowane jako int ?

funkcja flushinput

Kopiuj
while (_inbyte(((DLY_1S)*3)>>1) >= 0)
  rownanie zrobil bym osobno po za petla a dopiero pozniej bym wrzucil jako zdefiniowana wartocs w warunek petli

funkcja xmodemReceive

if (trychar) nie jest bool

co myslicie o tym ? jezeli jest ok to przejde przez kod dalej linijka po linijce

_13th_Dragon
if(crc) dla int crc nie jest błędem. Może zapomniałeś to nie java nie C# to C
0

Patryk27...czy moglbys udzielic troche info nt w ktorej lini jest odniesienie do tablicy po ujemnym indeksie bo ja tego nie widze ...

Patryk27
Moderator
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Wrocław
  • Postów:13042
1
Pijany Krawiec napisał(a):

Patryk27...czy moglbys udzielic troche info nt w ktorej lini jest odniesienie do tablicy po ujemnym indeksie bo ja tego nie widze ...

Nie ma - ale skoro autor wykorzystuje typ int, to daje do myślenia gdzie niby indeks może być ujemny (ponieważ int jest, zgodnie ze standardem C, liczbą ze znakiem). Dla indeksów powinno się w 99.9999% wykorzystywać size_t (mało kiedy ujemny indeks ma jakikolwiek sens).


edytowany 1x, ostatnio: Patryk27
0

Hej,

Mam pytanie odnosnie petli for i warunku

for (i = 0; i < (bufsz+(crc?1:0)+3); ++i)

jak zapisac to aby wygladalo lepiej ? domyslam sie, ze moge zastapic 'ternary operator' warunkiem if tylko nie wiem jak bo crc przyjmuje wartosc albo 0 albo 1 i jest zdefiniowane jako c

czy moglby mnie ktos poprawic ?

w tym mencie zrobilbym to tak gdyby crc bylo bool:

zdefiniowalbym

if crc {
unsigned zzz = bufsz + 4
for (i = 0; i < zzz ; ++ 1)
if ((c = _inbyte(DLY_1S)) < 0) goto reject;
*p++ = c;
}
else {
unsigned yyy = bufsz + 3
for (i = 0; i < zzz ; ++ 1)
if ((c = _inbyte(DLY_1S)) < 0) goto reject;
*p++ = c;
}

_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:2 miesiące
1

Ma to być w funkcji:

Kopiuj
size_t size=bufsz+3+(crc>0);
for(unsigned char pend=p+size;p<pend;++p) if((*p=_inbyte(DLY_1S))<0) return false;
return true;

Poza tym podejrzewam że wystarczy zawsze dać +4 owszem czasami jeden krok za dużo, ale za to niewielka cena za lepsza czytelność.


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
edytowany 4x, ostatnio: _13th_Dragon
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)