2012-04-25 11 views
6

Pracuję nad jakąś pracą domową i chciałem wiedzieć, czy istnieje coś takiego jak zbyt wiele zagnieżdżonych w pętli. Czy istnieje kilka minusów zagnieżdżania się podczas pętli? Jeśli tak, to w jaki sposób jeden z nich mógłby zmienić fragment kodu, który mam poniżej?Czy występują problemy z zagnieżdżaniem wielu podczas pętli?

Poniżej znajduje się kod do odczytywania pliku po linii, analizowania pól rozdzielanych przez niektóre zdefiniowane ograniczniki i usuwania wiodącej spacji przed drukowaniem na konsolę.

// Read the file one line at a time 
while (fgets(lineStr, MAXLINELENGTH, fp) != NULL) 
{ 
    charPtr = strtok(lineStr, DELIMITERS); 

    // Loop until line is parsed 
    while (charPtr != NULL) 
    { 
     // Skip past leading whitespace 
     while (isspace(*charPtr)) 
      charPtr++; 

     puts(charPtr); 
     charPtr = strtok(NULL, DELIMITERS); 
    } 
} 
+6

Nie, nie ma problemu w zagnieżdżonych pętlach. – pmg

+1

Chociaż, możesz chcieć zamknąć niektóre z nich w metody odzwierciedlające to, co robią - ten ostatni staje się 'skipSpaces()' lub niektórymi. –

+0

jeśli dane wejściowe mogą zawierać znaki ujemne (* z wartościami większymi niż 127 *), możesz chcieć rzucić argument na 'isspace', aby uniknąć niezdefiniowanego zachowania:' isspace ((unsigned char) * charPtr) ' – pmg

Odpowiedz

6

To naprawdę subiektywny temat. Moim zdaniem, nie ma nic zasadniczo nie tak z trzema zagnieżdżonymi podczas pętli, ale osiągasz granicę akceptowalności. Gdybyś dodał jeden lub dwa kolejne poziomy zagnieżdżania, wówczas, moim zdaniem, przekroczysz granicę tego, co rozsądnie można oczekiwać od czytelnika. Ludzki mózg może zająć się tak dużą złożonością w dowolnym momencie.

Niektórzy ludzie będą sprzeczać się z moją opinią, że nie powinno być więcej niż jeden poziom zagnieżdżania w funkcji, i że funkcje nie powinny zawierać więcej niż około 10 linii kodu. Argumentem licznika jest to, że taka polityka może skutkować bardziej fragmentarycznym, rozłącznym kodem. Moja zasada jest taka, że ​​jeśli nie możesz wymyślić dobrej nazwy funkcji dla fragmentu kodu, to być może ten fragment kodu nie jest tak naprawdę przeznaczony jako samodzielna funkcja.

Patrząc na sposoby, w jakie można podzielić tę funkcję, istnieje kilka oczywistych opcji.

  1. Wyodrębnij część zewnętrzną while do osobnej funkcji. Ta wyodrębniona funkcja przetwarza pojedynczą linię. Łatwo nazwać i wyczyścić, aby przeczytać.
  2. Wyodrębnij pętlę while, która przeskoczy białe znaki do oddzielnej funkcji. To znowu będzie łatwe do nazwania i sprawi, że twój kod będzie łatwiejszy do odczytania. Usunąłbyś komentarz spacji, ponieważ nazwa wyodrębnionej funkcji uczyniłaby go niepotrzebnym. To chyba warto robić.

Jeśli zastosowano te pomysły następnie kod może wyglądać trochę tak:

char* skipWhitespace(char* str) 
{ 
    while (isspace(*str)) 
     str++; 
    return str; 
} 

void parseLine(char *lineStr) 
{ 
    charPtr = strtok(lineStr, DELIMITERS); 
    while (charPtr != NULL) 
    { 
     charPtr = skipWhitespace(charPtr); 
     puts(charPtr); 
     charPtr = strtok(NULL, DELIMITERS); 
    } 
} 
...... 
while (fgets(lineStr, MAXLINELENGTH, fp) != NULL) 
    parseLine(lineStr); 

Zauważ, że refaktoryzacji i nazewnictwo ekstrahowanych metodami sprawia komentarze trochę zbędne i usunąłem je. Inną dobrą zasadą jest to, że jeśli chcesz skomentować kod za dużo, to być może nie jest on jeszcze dobrze rozeznany.

Ostatecznie naprawdę nie ma sztywnych reguł i sprowadza się to do osądu i osobistych preferencji. Moim zdaniem kod w pytaniu jest bardzo czytelny i czytelny, ale wersja refaktoryzowana jest po prostu trochę jaśniejsza, moim zdaniem.

Nota prawna: Nie komentuję prawidłowości lub braku kodu. Po prostu zignorowałem ten aspekt.

+1

Podoba mi się twoja zasada "bez nazwy, bez funkcji". Oczywiście jest to tylko wskazówka, ale przynosi dobry punkt - jeśli nie możesz opisać, co ta funkcja mogłaby zrobić, prawdopodobnie nie potrzebujesz jej funkcji! – corsiKa

+0

Dzięki za refaktoryzowany kod. Będzie musiał zapytać prof., Czy woli, aby kod był taki, jaki jest, czy też wolałby, aby poszczególne zagnieżdżone pętle były refakturowane na ich własne funkcje. Podoba mi się pomysł, że nie mam komentarzy, ponieważ nazwa funkcji jest wystarczająco jasna, aby przekazać tę ideę. – Peter

+0

Który wolisz? Powinieneś przynajmniej mieć zdanie i być gotowym do dyskutowania w taki czy inny sposób, kiedy idziesz do swojego prof. –

3

Jedynym minusem jest czytelność, na którą nie ma żadnych twardych i szybkich reguł dotyczących ... chociaż więcej niż 3 gniazda zwykle drażnią każdego, z kim pracujesz. Jak powiedział inny plakat, czasami lepiej przełamać gniazdo, przenosząc pętlę do innej funkcji, ale to, co tu masz, jest dla mnie doskonale czytelne - i to jedyna prawdziwa metryka; czysta subiektywna opinia :)

0

Jak wspomniano wcześniej, jest to stosunkowo subiektywne. Jednak zagnieżdżenie pętli może mieć bezpośredni wpływ na wydajność kodu.Rozważ programowanie pamięci podręcznej o nazwie. Oznacza to, że chcesz rozmieścić swój kod w taki sposób, aby procesor mógł wstępnie pobierać (to znaczy przewidywać) następny blok danych do pamięci podręcznej, zanim będzie tego potrzebował. Pozwoli to na więcej trafień w pamięci podręcznej i szybszy dostęp do pamięci.

Należy zauważyć, że nie jest to szczególnie ważne w przypadku tego przykładu, jednak w przypadku wielu dostępów do pamięci może to być znaczny wzrost lub spadek wydajności. Jeśli przechodzisz wielowymiarową tablicę w sposób kolumnowy w architekturze wielkiej litery, możliwe jest wiele pomyłek w pamięci podręcznej (pamiętaj, że brak pamięci podręcznej jest bardzo kosztowny pod względem czasu rzeczywistego).

Tak więc pętle gniazdowania niekoniecznie są złe, ale z pewnością mogą mieć zauważalny wpływ na wydajność, zwłaszcza po pewnych arbitralnych numerach pętli n.

Powiązane problemy