2012-03-24 11 views
0

Guten Morgen ein und alles! Dies wird im Nachhinein eine dieser blendend einfachen Fragen sein, aber für das Leben von mir bin ich ratlos. Ich gehe einige der Übungen in der Programmiersprache C durch und habe es geschafft, Code zu schreiben, um eine Schleife zu initialisieren. Nach etwas Googeln habe ich bessere Möglichkeiten gefunden, eine Schleife auf 0 zu initialisieren, aber ich verstehe nicht, warum die Schleife, die ich geschrieben habe, nicht fertig ist. Ich habe den Debugger verwendet, um herauszufinden, dass es daran liegt, dass die c-Variable niemals 50 erreicht, sondern 49 erreicht und dann auf 0 rollt, aber ich kann nicht herausfinden, warum sie rollt. Der Code ist unten angehängt, weiß jemand, was hier vor sich geht?C-Schleife wird nicht beendet

#include <stdio.h> 
#define IN 1 
#define OUT 0 

/* Write a program to print a histogram of the lengths of words in 
    itsinput. */ 
main() 
{ 
    int c=0; 
    int histogram[50]={0} 
    int current_length=0; 
    int state=OUT; 

    //Here we borrow C so we don't have to use i 
    printf("Initializing...\n"); 
    while(c<51){ 
     histogram[c] =0; 
     c=c+1; 
    } 
    c=0; 
    printf("Done\n"); 

    while((c=getchar()) != EOF){ 
     if((c==32 || c==10) && state==IN){ 
      //End of word 
      state=OUT; 
      histogram[current_length++]; 
     }else if((c>=33 && c<=126) && state==OUT){ 
      //Start of word 
      state=IN; 
      current_length=0; 
     }else if((c>=33 && c<=126) && state==IN){ 
      //In a word 
      current_length++; 
     } else { 
      //Not in a word 
      //Example, " " or " \n " 
      ; 
     } 
    } 

    //Print the histogram 
    //Recycle current_length to hold the length of the longest word 
    //Find longest word 
    for(c=0; c<50; c++){ 
     if(c>histogram[c]) 
      current_length=histogram[c]; 
    } 
    for(c=current_length; c>=0; c--){ 
     for(state=0; state<=50; state++){ 
      if(histogram[c]>=current_length) 
       printf("_"); 
      else 
       printf(" "); 
     } 
    } 
} 
+1

Beachten Sie diese Zeile: 'while (c <51)'! – Till

+1

Ein Semikolon fehlt nach der Deklaration 'int histogram [50] = {0}'. Da Sie 'histogram' in der Deklaration initialisiert haben, müssen Sie dies nicht erneut in der Schleife tun, die nach' c <50', nicht nach 'c <51' suchen soll. –

+0

Verwerten Sie niemals Variablen. Machen Sie ihren Bereich so lokal wie möglich (klein) und deklarieren Sie bei Bedarf neue. Der Compiler wird dies trotzdem optimieren. – bitmask

Antwort

5

Es ist, weil histogram[c] = 0 schreibt über die histogram Speicher, wenn c = 50. So im Wesentlichen überschreibt histogram[50] c und macht es 0.

Dies geschieht, weil Arrays von 0 in C. So der letzten gültigen Index in einer 50-Element-Array 49 gestartet ist.

Technisch, während interessant und verwertbar können Sie sich nicht darauf verlassen. Es ist eine Manifestation von undefiniertem Verhalten. Der Speicher könnte leicht ein anderes Layout haben, das Dinge "nur funktionieren lässt" oder etwas Lustigeres macht.

1

histogram hat 50 Elemente: von Index 0 bis Index 49
Sie versuchen, zu indizieren 50. ALLE WETTEN

tun

while (c < 50) 

oder ausgeschaltet sind, zu schreiben Magie zu vermeiden Konstanten

while (c < sizeof histogram/sizeof *histogram) 
+0

Nicht alle Konstanten sind magisch. Ein einfaches 'const int histogram_size = 50;' würde genauso gut funktionieren und (IMO) besser lesbar sein als 'sizeof histogram/sizeof * histogram'. – Caleb

+0

@Caleb: In C erstellt eine 'const int' Definition ein schreibgeschütztes Objekt, keine Konstante. Manchmal braucht man wirklich eine Konstante: 'sizeof arr/sizeof * arr' ist eine solche Konstante. – pmg

+0

Sie erhalten die gleiche Nummer in beide Richtungen. Wenn Sie die Größe von math verwenden, müssen Sie die Array-Größe noch irgendwo angeben. So können Sie dem Wert einen Namen geben und 'int histogram [histogram_size];' sagen, um 'histogram' zu deklarieren, oder Sie können' int histogram [50]; 'sagen. Ich denke, dass ersteres besser auf die "magische Konstante" anspricht, die Sie angesprochen haben. – Caleb

0

Sie greifen auf die Elemente 0 bis 50 im Histogramm zu, das nur die Elemente 0 bis 49 enthält (C/C++ verwendet die Nullindexierung, so dass das maximale Element eines Arrays immer die Größe 1 hat).

Um Fehler wie dies zu vermeiden, können Sie das Histogramm Größe als Konstante definieren könnten, und dass auf das Histogramm Array, für alle Operationen verwenden:

#define HISTOGRAM_SIZE 50 

Oder (funktioniert nur für C99 oder C++, siehe weiter unten Kommentar):

const int HISTOGRAM_SIZE = 50; 

Dann:

int histogram[HISTOGRAM_SIZE]; 

Und:

'#define' ist eine C-Präprozessor-Anweisung und wird vor der Kompilierung verarbeitet. Für den Compiler sieht es so aus, als hätten Sie überall 50 geschrieben, wo HISTOGRAM_SIZE verwendet wird, so dass Sie keinen zusätzlichen Overhead bekommen.

'Const Int' gibt Ihnen eine ähnliche Lösung, die in vielen Fällen das gleiche Ergebnis wie mit der Definition geben wird (ich bin nicht 100% sicher unter welchen Umständen, andere sind frei zu erarbeiten), wird aber auch geben Sie den zusätzlichen Bonus der Typprüfung.

+1

In C89 definiert die 'const int' -Definition keine Konstante, die in Array-Dimensionen verwendbar ist (sie definiert ein schreibgeschütztes Objekt). C99 erlaubt VLAs (Variable Length Arrays), die keine Konstanten zur Angabe der Größe benötigen. – pmg

+0

Ah, danke! Ich habe das obige bearbeitet, um das zu reflektieren. – sonicwave

Verwandte Themen