在c中为数组赋值时出现意外结果

发布于 2024-12-22 12:01:34 字数 2969 浏览 1 评论 0原文

我正在阅读C 编程语言第二版。我已经完成了这个练习 [第 1.6 节第 1-13 页,]。 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;


}

~ ~

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].

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.

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;


}

~
~

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

甜是你 2024-12-29 12:01:34

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

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

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

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

锦欢 2024-12-29 12:01:34

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

  1. 花点时间输入有意义的变量名称。或者至少是被截断的。像 NumTabs 或任何适合您风格的东西。
  2. 降低你的缩进风格。适当的缩进可以更容易地理解程序流程。

因此,当您执行此操作时,您会犯一个明显的错误:

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 个。如果你想能够访问 count[11] 你必须将 count 声明为

int count[12];

这称为差一错误。这是一个非常基本的错误,但不要感觉太糟糕,即使是专家最终也会犯下相同的基本错误(通常更复杂和严重)的版本。一般来说,字符串处理也是一个真正的痛苦。

无论如何,如果这还不够,如果您想从概念上想象它 - 这不是它的工作原理,但从概念上讲 - 您的数组分配 11 个 int,并且“count”是指向它的指针。所以(pointer+0)将指向第一个整数,这与pointer[0]是一样的。 (指针+1)这与指针[1]指向第二个整数是一样的。 (pointer+5)/pointer[5] 将指向第 6 个整数,(pointer+11)/pointer[11] 将指向第 12 个整数 - 这不存在,因为它们只有 11 个。

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. Get your indentation style down. Proper indentation allows easier understanding of the program flow.

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:

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

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.

半寸时光 2024-12-29 12:01:34

Two 您的程序包含的三个附加点(错误)是

  • 整数除法产生的结果是整数,因此:

    float kbcount = (nc-1)/1024;

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

我相信您想说的是:

float kbcount = (nc - 1) / 1024.0;

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

接下来,

  • 您可以简化确定 c 是单词的一部分还是“空白”(空格、制表符、换行符)的一部分的逻辑,以使您的程序更短且更易于理解。

例如:

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... */

请注意,使用更好的变量名称来阅读是多么容易。

最后,

  • 您是新手或初学者,不是菜鸟

参考:

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

老实说,每个程序员在刚开始学习新的编程语言时都会犯大量错误。但这是自然学习过程的一部分。您可以通过探索、尝试事物以及发现哪些有效、哪些无效来学习。这是一个过程,希望您能够享受努力的挑战,不仅要思考问题的解决方案,还要将解决方案解构为逻辑上的小步骤,并将其编写出来正确地使用合成语言,在本例中为C

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;

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

What I believe you want wanted to say is:

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.

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.

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文