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.
你犯了三个主要错误。前两个是风格,让我 - 和大多数其他人 - 不想阅读代码和帮助。最后一个是你的逻辑错误......好吧,一个,无论如何。
- Take the time to type out meaningful variable names. Or at least truncated ones. Like NumTabs or whatever fits your style.
- Get your indentation style down. Proper indentation allows easier understanding of the program flow.
花时间输入有意义的变量名称。或者至少是截断的。像NumTabs或任何适合你的风格。
缩小你的缩进风格。适当的缩进可以更容易地理解程序流程。
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.
你犯了三个主要错误。前两个是风格,让我 - 和大多数其他人 - 不想阅读代码和帮助。最后一个是你的逻辑错误......好吧,一个,无论如何。
- Take the time to type out meaningful variable names. Or at least truncated ones. Like NumTabs or whatever fits your style.
- Get your indentation style down. Proper indentation allows easier understanding of the program flow.
花时间输入有意义的变量名称。或者至少是截断的。像NumTabs或任何适合你的风格。
缩小你的缩进风格。适当的缩进可以更容易地理解程序流程。
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。