簡體   English   中英

為什么用奇怪的方式初始化此數組?

[英]Why is this array being initialized in an odd way?

我正在閱讀K&R第二版,但在理解練習1-13時遇到困難。 答案是這樣的代碼

#include <stdio.h>

#define MAXHIST 15  
#define MAXWORD 11  
#define IN 1        
#define OUT 0      


main()
{

    int c, i, nc, state;
    int len;
    int maxvalue;
    int ovflow;
    int wl[MAXWORD];

    state = OUT;
    nc = 0;         
    ovflow = 0;

    for (i = 0; i < MAXWORD; i++)
        wl[i] = 0;  

    while ((c = getchar()) != EOF)
    {
        if(c == ' ' || c == '\n' || c == '\t')
        {
            state = OUT;            
            if (nc > 0)
            {
                if (nc < MAXWORD)   
                    ++wl[nc];       
                else
                    ++ovflow;       
            }                       
            nc = 0;                 
        }
        else if (state == OUT)
        {
            state = IN;             
            nc = 1;                 
        }
        else
            ++nc;                   
    }

    maxvalue = 0;
    for (i = 1; i < MAXWORD; ++i)
    {
        if(wl[i] > maxvalue)
            maxvalue = wl[i];       
    }

    for(i = 1; i < MAXWORD; ++i)
    {
        printf("%5d - %5d : ", i, wl[i]);
        if(wl[i] > 0)
        {
            if((len = wl[i] * MAXHIST / maxvalue) <= 0)
                len = 1;
        }
        else
            len = 0;

        while(len > 0)
        {
            putchar('*');
            --len;
        }
        putchar('\n');
    }

    if (ovflow > 0)
        printf("There are %d words >= %d\n", ovflow, MAXWORD);

    return 0;

}

在頂部, wl被聲明和初始化。 我不明白的是,如果它只計算單詞的長度,為什么要遍歷它並將所有內容都設置為零? 它不會跟蹤有多少個單詞,而只會跟蹤單詞的長度,因此為什么將所有內容都設置為0?

我知道目前還不清楚,這只是過去20分鍾給我的壓力,我不知道為什么。

數組wl[]i個元素是在輸入文件中找到的長度為i的單詞數。 必須先將wl[]數組初始化為零,以便++wl[nc]; 不會通過嘗試使用未初始化的變量而導致未定義的行為,因此表示不存在的字長的數組元素反映未找到此類字長。

注意, ++wl[nc]遞增值wl[nc]長度的字時nc遇到。 如果未初始化數組,則代碼首次嘗試遞增數組元素時,它將嘗試遞增不確定值。 此嘗試將導致未定義的行為。

此外,表示在輸入中找不到的字長計數的數組索引應保持零值,但如果不進行零初始化,則這些值將不確定。 即使嘗試打印這些不確定的值也會導致未定義的行為。

道德觀念:在嘗試使用變量之前,將變量初始化為明智的值,或將值存儲在其中。

使用數組初始值設定項對wl[]數組進行零初始化似乎更加簡單明了:

int wl[MAXWORD] = { 0 };

此后,就不需要將另一個文件的數組值設置為零(除非再次使用該數組)的循環。 但是,發布的代碼來自Tondo和Gimpel的The C Answer Book 本書以K&R的形式提供了第二版K&R中的練習的解決方案,並且僅使用每次練習之前書中介紹的思想。 此練習1.13在“第1章-教程簡介”中進行。 這是該語言的簡短介紹,缺少許多細節,稍后將在書中找到。 至此,已經引入了賦值和數組,但是還沒有引入數組初始化器(必須等到第4章),並且到目前為止,使用數組的K&R代碼已經使用循環對數組進行了初始化。 從30歲以上的書的入門章節中,不要過多地了解代碼風格。

自K&R發布以來,C語言發生了許多變化,例如main()不再是main()函數的有效函數簽名。 請注意,函數簽名必須是int main(void)int main(int argc, char *argv[]) (或int main(int argc, char **argv) )之一,並為實現定義了警告main()簽名。

一切都設置為0,因為如果不初始化數組,則將使用隨機數初始化數組。 隨機數將導致程序錯誤。 不必循環遍歷數組的每個位置,您可以執行以下操作: int wl[MAXWORD] = {0}; int wl[MAXWORD]; 這會將0放置在數組中的每個位置,因此您不必執行循環。

我編輯了您的代碼並在處理過程中添加了一些注釋,以解釋發生了什么。 我還更改了您的某些直方圖計算,因為它們對我而言似乎沒有意義。

底線:它使用原始的“狀態機”來計算不是空格的每組字符中的字母。 它將其存儲在wl[] ,以便wl[i]包含一個整數,該整數告訴您有多少個字符組(有時稱為“令牌”)的字長為i 因為這是通過增加w[]的適當元素來完成的,所以必須將每個元素初始化為零。 否則,將導致不確定的行為,但可能會導致w[]每個元素中的計數變得荒謬而荒謬。

另外,任何長度不能在w[]反映的令牌都將被記錄在ovflow變量中,因此最后將對每個令牌進行核算。

#include <stdio.h>

#define MAXHIST 15  
#define MAXWORD 11  
#define IN 1        
#define OUT 0      


int main(void) {
  int c, i, nc, state;
  int len;
  int maxvalue;
  int ovflow;
  int wl[MAXWORD];

  // Initializations
  state = OUT;  //Start off not assuming we're IN a word
  nc = 0;       //Start off with a character count of 0 for current word
  ovflow = 0;   //Start off not assuming any words > MAXWORD length

  // Start off with our counters of words at each length at zero
  for (i = 0; i < MAXWORD; i++) {
    wl[i] = 0;  
  }

  // Main loop to count characters in each 'word'
  // state keeps track of whether we are IN a word or OUTside of one
  // For each character in the input stream...
  //   - If it's whitespace, set our state to being OUTside of a word
  //     and, if we have a character count in nc (meaning we've just left
  //     a word), increment the counter in the wl (word length) array.
  //     For example, if we've just counted five characters, increment
  //     wl[5], to reflect that we now know there is one more word with 
  //     a length of five.  If we've exceeded the maximum word length,
  //     then increment our overflow counter.  Either way, since we're
  //     currently looking at a whitespace character, reset the character
  //     counter so that we can start counting characters with our next
  //     word. 
  //   - If we encounter something other than whitespace, and we were 
  //     until now OUTside of a word, change our state to being IN a word
  //     and start the character counter off at 1.
  //   - If we encounter something other than whitespace, and we are
  //     still in a word (not OUTside of a word), then just increment
  //     the character counter.
  while ((c = getchar()) != EOF) {
    if (c == ' ' || c == '\n' || c == '\t') {
      state = OUT;            
      if (nc > 0) {
        if (nc < MAXWORD) ++wl[nc];
        else ++ovflow;       
      }                       
      nc = 0;                 
    } else if (state == OUT) {
      state = IN;             
      nc = 1;                 
    } else {
      ++nc;
    }
  }

  // Find out which length has the most number of words in it by looping
  // through the word length array. 
  maxvalue = 0;
  for (i = 1; i < MAXWORD; ++i) {
    if(wl[i] > maxvalue) maxvalue = wl[i];       
  }

  // Print out our histogram
  for (i = 1; i < MAXWORD; ++i) {
    // Print the word length - then the number of words with that length
    printf("%5d - %5d : ", i, wl[i]);

    if (wl[i] > 0) {
      len = wl[i] * MAXHIST / maxvalue;
      if (len <= 0) len = 1;
    } else {
      len = 0;
    }

    // This is confusing and unnecessary.  It's integer division, with no
    // negative numbers.  What we want to have happen is that the length
    // of the bar will be 0 if wl[i] is zero; that the bar will have length
    // 1 if the bar is otherwise too small to represent; and that it will be
    // expressed as some fraction of MAXHIST otherwise. 
    //if(wl[i] > 0)
    //    {
    //        if((len = wl[i] * MAXHIST / maxvalue) <= 0)
    //            len = 1;
    //    }
    //    else
    //        len = 0;

    // Multiply MAXHIST (our histogram maximum length) times the relative 
    // fraction, i.e., we're using a histogram bar length of MAXHIST for
    // our statistical mode, and interpolating everything else. 
    len = ((double)wl[i] / maxvalue) * MAXHIST; 

    // Our one special case might be if maxvalue is huge, a word length
    // with just one occurrence might be rounded down to zero.  We can fix
    // that manually instead of using a weird logic structure.
    if ((len == 0) && (wl[i] > 0)) len = 1;

    while (len > 0) {
      putchar('*');
      --len;
    }

    putchar('\n');
  }

  // If any words exceeded the maximum word length, say how many there were.
  if (ovflow > 0) printf("There are %d words >= %d\n", ovflow, MAXWORD);

  return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM