繁体   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