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

时间:2022-09-25 08:58:02

I am reading C The Programming Language Second Edition. I've come to this exercise [1-13 in Section 1.6, pg. 24 2nd ed].

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

Write a program to print a histogram of the lengths of words in its input. It is easy to draw the histogram with the bars horizontal; a vertical orientation is more challenging.

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

Everything works pretty well I think except when I try to determine whether the last word count (VARIABLE tmp) is <=10 or > 10 then assign that to the corresponding index in count[tmp-1] or count[11] if it is greater than. I don't even care about printing an actual histogram I would just like to have a valid array representation for now. Below is the output of my program when it runs.

一切都运行良好我认为除非我试图确定最后一个字数(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 

Here is my code

这是我的代码

#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 个解决方案

#1


10  

c arrays are indexed from 0. count[11]++; is out of bounds of the array.

c数组的索引是从0. count [11] ++;超出了数组的范围。

Valid indices for an 11 element array are index 0 through 10 inclusive. The 11th element in the array count is at count[10].

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

#2


4  

You're making three major errors. The first two are stylistic and make me - and most other people - not want to read the code and help. The last is your logic error...well, one, anyway.

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

  1. Take the time to type out meaningful variable names. Or at least truncated ones. Like NumTabs or whatever fits your style.
  2. 花时间输入有意义的变量名称。或者至少是截断的。像NumTabs或任何适合你的风格。

  3. Get your indentation style down. Proper indentation allows easier understanding of the program flow.
  4. 缩小你的缩进风格。适当的缩进可以更容易地理解程序流程。

So, your big glaring error is when you do this:

所以,当你这样做时,你明显的错误就是:

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

In the code, it is defined higher up as:

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

int count[11];

That array has 11 integers in it. However, you do not start referencing them from 1. You start referencing them from 0. count[0], count[1]...count[10] are all valid. Like so:

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

0 1 2 3 4 5 6 7 8 9 10

0 1 2 3 4 5 6 7 8 9 10

As you can see that's 11 numbers even though it only goes up to 10. If you'd like to be able to access count[11] you have to declare count as

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

int count[12];

This is known as an off-by-one error. It's a pretty basic one but don't feel too bad, even gurus end up making (usually more complex and grievous) versions of the same basic mistake. String processing is also a real pain in general.

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

Anyway, if that wasn't enough, if you'd like to imagine it conceptually - this isn't how it WORKS, but conceptually - your array allocates 11 int's and 'count' is a pointer to it. So (pointer+0) would point to the 1st integer, which is the same thing as saying pointer[0]. (pointer+1) which is the same thing as saying pointer[1] would point to the 2nd integer. (pointer+5)/pointer[5] would point to the 6th integer, (pointer+11)/pointer[11] to the 12th - which doesn't exist, since there are only 11 of them.

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

#3


1  

Two Three additional points (errors) that your program contain are

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

  • The division of integers produces a result that is an integer, so in :

    整数除法产生一个整数的结果,所以在:

    float kbcount = (nc-1)/1024;

    float kbcount =(nc-1)/ 1024;

The variable kbcount is set to the integer result of the integer division of nc - 1 by 1024.

变量kbcount被设置为整数除以nc-1乘以1024的整数结果。

What I believe you want wanted to say is:

我相信你想要说的是:

float kbcount = (nc - 1) / 1024.0;

float kbcount =(nc - 1)/ 1024.0;

As one of parts (the denominator in this case) is a floating point number, the rules of precedence converts (promotes) both parts into a floating point value, and then the division becomes a floating point division, so the results will be a floating point value with its fractional (decimal) value. Read Section 2.7 (pg. 42) of The C Programming Language, for a better explanation.

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

Next,

  • You can simplify the logic of determining whether a c is part of a word or part of the "whitespace" (spaces, tabs, newlines) to make you program shorter and easier to understand.
  • 您可以简化确定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... */

Notice how much easier it is to read with better variable names.

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

And finally,

  • You are a novice or a beginner, not a noob.
  • 你是新手或初学者,不是菜鸟。

Ref:

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

Honestly, every programmer makes tons of mistakes when they are beginning, and when learning a new programming language. But it is part of the natural learning process. You learn by exploring, trying new things, and discovering both, what works, and what doesn't. It is a process, and hopefully you can come to enjoy the challenges of the effort to not only think of a solution to a problem, but to deconstruct the solution into logical bite-sized steps, and write it correctly in a synthetic language, in this case, C.

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

#1


10  

c arrays are indexed from 0. count[11]++; is out of bounds of the array.

c数组的索引是从0. count [11] ++;超出了数组的范围。

Valid indices for an 11 element array are index 0 through 10 inclusive. The 11th element in the array count is at count[10].

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

#2


4  

You're making three major errors. The first two are stylistic and make me - and most other people - not want to read the code and help. The last is your logic error...well, one, anyway.

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

  1. Take the time to type out meaningful variable names. Or at least truncated ones. Like NumTabs or whatever fits your style.
  2. 花时间输入有意义的变量名称。或者至少是截断的。像NumTabs或任何适合你的风格。

  3. Get your indentation style down. Proper indentation allows easier understanding of the program flow.
  4. 缩小你的缩进风格。适当的缩进可以更容易地理解程序流程。

So, your big glaring error is when you do this:

所以,当你这样做时,你明显的错误就是:

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

In the code, it is defined higher up as:

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

int count[11];

That array has 11 integers in it. However, you do not start referencing them from 1. You start referencing them from 0. count[0], count[1]...count[10] are all valid. Like so:

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

0 1 2 3 4 5 6 7 8 9 10

0 1 2 3 4 5 6 7 8 9 10

As you can see that's 11 numbers even though it only goes up to 10. If you'd like to be able to access count[11] you have to declare count as

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

int count[12];

This is known as an off-by-one error. It's a pretty basic one but don't feel too bad, even gurus end up making (usually more complex and grievous) versions of the same basic mistake. String processing is also a real pain in general.

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

Anyway, if that wasn't enough, if you'd like to imagine it conceptually - this isn't how it WORKS, but conceptually - your array allocates 11 int's and 'count' is a pointer to it. So (pointer+0) would point to the 1st integer, which is the same thing as saying pointer[0]. (pointer+1) which is the same thing as saying pointer[1] would point to the 2nd integer. (pointer+5)/pointer[5] would point to the 6th integer, (pointer+11)/pointer[11] to the 12th - which doesn't exist, since there are only 11 of them.

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

#3


1  

Two Three additional points (errors) that your program contain are

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

  • The division of integers produces a result that is an integer, so in :

    整数除法产生一个整数的结果,所以在:

    float kbcount = (nc-1)/1024;

    float kbcount =(nc-1)/ 1024;

The variable kbcount is set to the integer result of the integer division of nc - 1 by 1024.

变量kbcount被设置为整数除以nc-1乘以1024的整数结果。

What I believe you want wanted to say is:

我相信你想要说的是:

float kbcount = (nc - 1) / 1024.0;

float kbcount =(nc - 1)/ 1024.0;

As one of parts (the denominator in this case) is a floating point number, the rules of precedence converts (promotes) both parts into a floating point value, and then the division becomes a floating point division, so the results will be a floating point value with its fractional (decimal) value. Read Section 2.7 (pg. 42) of The C Programming Language, for a better explanation.

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

Next,

  • You can simplify the logic of determining whether a c is part of a word or part of the "whitespace" (spaces, tabs, newlines) to make you program shorter and easier to understand.
  • 您可以简化确定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... */

Notice how much easier it is to read with better variable names.

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

And finally,

  • You are a novice or a beginner, not a noob.
  • 你是新手或初学者,不是菜鸟。

Ref:

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

Honestly, every programmer makes tons of mistakes when they are beginning, and when learning a new programming language. But it is part of the natural learning process. You learn by exploring, trying new things, and discovering both, what works, and what doesn't. It is a process, and hopefully you can come to enjoy the challenges of the effort to not only think of a solution to a problem, but to deconstruct the solution into logical bite-sized steps, and write it correctly in a synthetic language, in this case, C.

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