将值分配给数组时出现意外结果在c

时间:2011-12-23 23:44:08

标签: c arrays histogram

我正在阅读 C编程语言第二版。我参加了这个练习[1.6节中的1-13, pg。 24第二版]。

  

编写程序以打印其中单词长度的直方图   输入。可以很容易地绘制水平条形图的直方图;一个   垂直方向更具挑战性。

除非我尝试确定最后一个字数(VARIABLE tmp)是< = 10还是> 10然后,如果它大于,则将其分配给count [tmp-1]或count [11]中的相应索引。我甚至不关心打印一个实际的直方图,我现在想拥有一个有效的数组表示。下面是程序运行时的输出。

asdasd 
_________________________________
 1  2  3  4  5  6  7  8  9 10 11 
   (x-axis) Length of words 
---------------------------------
[0 SPACE] [0 NEWLINE] [0 TAB] 
[1 WORD] [0.000 KILOBYTE] [6 CHAR]



6---


ARRAy= 1  1  1  1  1  2  0  0  0  0 

这是我的代码

#include <stdio.h>
#define MAX 10


int main (void) {
    //
    int nc,nw,nt,ns,nl;  //nc = bytes, nw = words, nt = tabs, ns = spaces, nl = newlines
    nc = nw = nt = ns = nl = 0;
    //
    int c;                     //getchar()
    int done = 0;             //don't even know I'm a noob just ignore...
    int tmp = 0;              //last word count (this works well)
    int array[MAX + 1];      //For outputting screen formatters like ---
    int count[11];           //THIS is whats broken random values
    int state = 0;
    int waslast = 0;
    float kbcount = 0;
    for (c = 0; c <= MAX; c++)
    count[c] = 0;

    while (done == 0) {
        c = getchar();
        ++nc;

        if (c == ' ' || c == '\n' || c == '\t') {
            waslast = 1;



            if (c == '\t') {
                ++nt;
                state = tmp;
                tmp = 0;
            }
            else if (c == '\n') {
                ++nl;
                state = tmp;
                tmp = 0;
            }
            else if (c == ' ') {
                ++ns;
                state = tmp;
                tmp = 0;
            }
        }

        if (c == EOF) {
            done = 1;
        }
        else if (c != ' ' && c != '\n' && c != '\t') {
            tmp++;
            state = tmp;
            if (waslast == 1) {
                nw++;
                waslast=0;
            }
            if (nc == 1)
                nw++;
        }

        if (tmp <= 10)
            count[tmp-1]++;       //Completely random assignments
        else
            count[11]++;          //This is broken
    }



    // END WHILE
    //
    //



    printf("\n");
    for (c = 1; c <= MAX + 1; c++) {
        printf("___");

    }

    printf("\n");

    for (c = 1; c <= MAX + 1; c++) {
        array[c] = c;
        printf("%2d ", array[c]);
    }

    printf("\n   (x-axis) Length of words \n");

    for (c = 1; c <= MAX + 1; c++){
        printf("---");
    }

    kbcount = (nc-1)/1024;

    printf("\n[%d SPACE] [%d NEWLINE] [%d TAB] \n[%d WORD] [%.3f KILOBYTE] [%d CHAR]\n\n\n\n%d---\n\n\n",
           ns,nl,nt,nw,kbcount,(nc -(nl+nt+ns))-1,state);

    printf("ARRAy=");
    for (c = 0; c<MAX ;++c)
        printf(" %d ",count[c]);
    return 0;


}

〜 〜

3 个答案:

答案 0 :(得分:10)

c数组从0开始编制索引。count[11]++;超出数组范围。

11元素数组的有效索引是索引0到10(包括0和10)。数组count中的第11个元素位于count[10]

答案 1 :(得分:4)

你犯了三个主要错误。前两个是风格,让我 - 和大多数其他人 - 不想阅读代码和帮助。最后一个是你的逻辑错误......好吧,无论如何。

  1. 花时间输入有意义的变量名称。或者至少是截断的。像NumTabs或任何适合你风格的东西。
  2. 缩小你的缩进风格。适当的缩进可以更容易地理解程序流程。
  3. 所以,当你这么做时,你明显的错误就是:

    count[11]++;          //This is broken
    

    在代码中,它被定义为更高版本:

    int count[11];
    

    该数组中有11个整数。但是,您不会从1开始引用它们。您开始从0开始引用它们.count [0],count [1] ... count [10]都是有效的。像这样:

    0 1 2 3 4 5 6 7 8 9 10

    你可以看到11个数字,即使它只有10个。如果你想能够访问计数[11]你必须声明计数为

    int count[12];
    

    这被称为一个错误的错误。这是一个非常基本的,但不要感觉太糟糕,甚至大师最终制作(通常更复杂和严重)同一基本错误的版本。字符串处理通常也是一种真正的痛苦。

    无论如何,如果这还不够,如果你想在概念上想象它 - 这不是它的工作方式,但从概念上讲 - 你的数组分配11个int,'count'是指向它的指针。所以(指针+ 0)将指向第一个整数,这与指针[0]相同。 (指针+ 1)与指针[1]指向第二个整数的情况相同。 (指针+ 5)/指针[5]将指向第6个整数,(指针+ 11)/指针[11]到第12个 - 这是不存在的,因为它们只有11个。

答案 2 :(得分:1)

两个程序包含的三个附加点(错误)

  • 整数除法产生的结果是整数,所以在:

    float kbcount = (nc-1)/1024;

变量kbcount设置为nc - 1整数除法的整数结果1024

我相信你想要说的是:

float kbcount = (nc - 1) / 1024.0;

由于其中一个部分(在这种情况下为分母)是浮点数,优先规则将(提升)两个部分转换为浮点值,然后除法变为浮点数点分割,因此结果将是浮点值 其小数(十进制)值。阅读C编程语言的第2.7节(第42页),以获得更好的解释。

接下来,

  • 您可以简化确定c是否为“空白”(空格,制表符,换行符)的一部分或一部分的逻辑,以使您的程序更短,更容易理解。

E.g:

enum state_t = {whitespace, printable};
...

enum state_t state = whitespace;
while (EOF != (c = getchar())) {
    bytes++;

    if (is_whitespace(c)) {
        if (state == printable) { /* the whitespace ends the 'word' state */
            count[length % MAX]++;
            length = 0;
        }
        ...
        state = whitespace;
    } else {
        if (state == whitespace) {
            /* starting a new word */
            wordcount++;
        }
        length++ /* word length */
        state = printable;
    }
    ...
    /* anything else you want to do */
}
/* done reading standard input (stdin), now print report... */

请注意,使用更好的变量名称阅读会更容易。

最后,

  • 您是新手或初学者, noob

价:

//don't even know I'm a noob just ignore...

老实说,每个程序员在开始时以及在学习新的编程语言时都会犯错误。但它是自然学习过程的一部分。您可以通过探索,尝试事物,并发现两者,哪些有用以及来学习。这是一个过程,希望您能够享受努力的挑战,不仅要考虑问题的解决方案,而且要将解决方案解构为逻辑一口大小的步骤,并编写它正确地使用合成语言,在这种情况下,C