单词长度直方图练习提示?
我正在通过《C 编程语言》一书学习 C,我正在尝试解决练习 1.13:
“编写一个程序来打印输入中单词长度的直方图。很容易 绘制条形水平的直方图;垂直方向更具挑战性。”
我编写了代码,但是当我按 CTRL+Z(文件结束)时,它显示全零而不是单词的长度。
任何人都可以给我提示我在哪里吗出了问题吗?
#include <stdio.h>
/* print a histogram of the length of words from input */
main()
{
int c, i, wordn, space;
int lengthn[20];
wordn = space = 0;
for (i = 0; i < 20; ++i)
lengthn[i] = 0;
while ((c = getchar()) != EOF) {
if (c == ' ' || c == '\t' || c == '\n')
if (space == 1) {
++wordn;
space = 0;
++i;
}
if (c != ' ' && c != '\t' && c != '\n') {
++lengthn[i];
space = 1;
}
}
printf("Length: ");
for (i = 0; i < 16; ++i)
printf("%d ", lengthn[i]);
printf("\n --------------------------------------------------------------\n");
printf("Word: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\n");
}
I'm learning C with "The C Programming Language" book, and I'm trying to solve exercise 1.13:
"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."
I wrote the code, but when I press CTRL+Z (End-of-File), it shows all zeros instead of the length of words.
Could anyone give me a hint on where I'm going wrong?
#include <stdio.h>
/* print a histogram of the length of words from input */
main()
{
int c, i, wordn, space;
int lengthn[20];
wordn = space = 0;
for (i = 0; i < 20; ++i)
lengthn[i] = 0;
while ((c = getchar()) != EOF) {
if (c == ' ' || c == '\t' || c == '\n')
if (space == 1) {
++wordn;
space = 0;
++i;
}
if (c != ' ' && c != '\t' && c != '\n') {
++lengthn[i];
space = 1;
}
}
printf("Length: ");
for (i = 0; i < 16; ++i)
printf("%d ", lengthn[i]);
printf("\n --------------------------------------------------------------\n");
printf("Word: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15\n");
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
(因为OP要求的是提示,而不是解决方案)
那么......在这个循环之后
i
等于什么?接下来你会在哪里使用它?
(Because the OP is asking for hints, not the solution)
So ... what does
i
equal after this loop?And where do you use it next?
此循环之后
i
的值将为i=20
,因此您必须在 while 循环之前初始化
i
The value of
i
after this loop will bei=20
so you must initialize
i
before while loop我写了一个垂直方向的代码。
我是 C 新手,所以可能代码不好。
I wrote a code for the vertical orientation.
I'm new to C, so may be the code is not good.
首先,这是原始代码的输出,仅更改一行:
100
对于测试来说肯定有点太大了。我们看到第一个问题:
20
的单词为负值存在一些 one_off 错误。
问题:
MAXLEN
长度的单词被忽略尚不清楚
MAXLEN
是否包含在内,但包含长度为MAXLEN< 的单词似乎更自然/code> 在直方图中。但无论如何,这些单词都应该被计算在内:在直方图中或在
overflow
计数中:这里将其排除,因为没有与
==
change 1
匹配的内容,我们得到
Now我们已经考虑到了 5 个单词。
更改 2
溢出中的巨大数字是由于此处的错误造成的
,因为在
printf
中索引将一直到MAXHIST
但wlen
从>0
到MAXHIST-1
。有很多方法可以纠正这个问题。这是这里使用的一个简单的方法:只需将 1 项添加到
wlen
数组中。并使用
,我们可以获得
有关代码的更多信息
所提供的代码基于 1978 年的一本书(K&R 圣经)。从那时起,很多事情都发生了变化。例如,C-Faq 经常被引用作为
C
编程的参考指南,大部分可以追溯到 90 年代。并且自 2005 年以来从未更新过...但是从那时起,
C
语言和编程概念一直在发生变化。很多。1
for
中声明i
。例如,在 C++ 中,我们可以在 switch 或 while 或 if 标头中声明变量。减少任何变量的范围(生命周期)非常重要,特别是那些具有简单名称(例如i
和j
)的变量。我们可以编写 just
我们也可以编写
和删除这个
for
循环,因为程序只使用数组运行一次。而不是
您应该使用
就可以了。但是仅用于打印
*
的第二个循环是多余的。现在,程序经过这些更改后,
示例输出
关于状态机的
使用
if
来控制状态,并且首先测试字母流,然后测试状态,很难遵循。一般来说,有限状态机是一些输入(在本例中为字母流)的过滤器,这些输入在循环中馈送,然后开关
获取状态
并执行其操作.FSM 状态必须在项目(本例中为字母)之前进行测试。这个想法是每个状态都是独立的,并且可以单独编码,甚至可以由不同的人和时间进行编码。
溢出应该是状态:当一个单词达到溢出计数时,所有剩余的字母都会被跳过,这是一种不同的行为,这样编码更容易。
EOF 也应该是一种状态:在
EOF
处,我们只是打印结果并终止。另一个示例
我不会一步步更改所提供的代码,而是在此处留下完整的
C 示例,示例输出和一些参数,以免帖子更大。
示例中的一些结果
p
假定默认长度为 4 个字母,但用户可以在命令行上提供值,如p 12
所示,最多为 12 个字母字母的话。echo t te tes test tests | 这样的行终端上的 p 4
运行程序,使用 4 作为最大长度,并将echo
和管道|
符号之间的文本作为输入,因此可以使测试更快而且更容易。的示例的完整代码
有关示例代码
作为示例,以下是
S_IN
状态,当我们在一个单词内部时,刚刚读取一个新的c
值:所有状态都使用类似的代码:字母上的开关,因此编写和管理状态的速度更快。上面我们看到了到其他 3 种状态的转换。
S_OVERFLOW
的代码类似:这就是我想要展示的内容。溢出的逻辑没有隐藏在
S_IN
内部,并且没有测试跳过剩余的字母。 FSM 使抽象模型变得更加容易。每个状态的代码可以由不同的人开发和测试。
Before anything, here is the output from the original code, changing just one line:
100
is for sure a bit too large for testing.And we see the first problems:
20
There are some one_off errors.
PROBLEM: words with
MAXLEN
length are ignoredIt is not clear if
MAXLEN
is inclusive or not, but it seems to be more natural to include words with lengthMAXLEN
in the histogram. But these words should be counted anyway: in the histogram or in theoverflow
count:it is excluded here, since there is no match for
==
change 1
and we get
Now we have the 5 words accounted for.
change 2
The giant number in overflow is due to an error here
since in the
printf
the index will go untilMAXHIST
butwlen
goes from0
toMAXHIST-1
.There are many ways to correct this. This is a simple one used here: just add 1 item to
wlen
array.and use
and we get
more about the code
The provided code is based on a book (K&R bible) from 1978. Since then many things changed. The C-Faq for example is often cited as reference guidelines for
C
programming, and dates back from the most part from the 90's. And was never updated since 2005...But
C
language and concepts in programming have been changing since then. A lot.1
i
inside thefor
. InC++
for example we can declare variables inswitch
orwhile
orif
header. It is important to reduce the scope --- lifetime --- of any variable, and specially those with naive names likei
andj
.We can write just
Also we can write
and delete this
for
loop, since the program runs just once with the array.Instead of
You should use
will do ok. But the second loop just for printing the
*
is redundant.the program now with these changes
sample output
about the state machine and another possible problem
using an
if
to control the states, and testing first the stream of letters and then the states is very hard to follow. In general Finite State Machines are filters of some input (a stream of letters in this case) that are fed in a loop, then aswitch
gets thestate
and does its thing.FSM states must be tested before the item (the letter in this case. The idea is that each state is independent and could be coded separately, even by diferent people and time.
overflow should be a state: when a word reaches the overflow count then all remaining letters are skipped. This is a different behavior and it is easier to code it this way.
EOF should be a state also: at
EOF
we just print the results and terminate.an alternative example
Instead of changing the provided code step by step I will leave here a complete
C
example, sample output and some arguments, in order to not have an even larger post.Some results from the example
p
assumes a default length of 4 letters, but the user can provide the value on the command line as inp 12
for a maximum of 12 letter words.echo t te tes test tests | p 4
on the terminal runs the program using 4 as the maximum length and the text betweenecho
and the pipe|
sign as input, so it makes testing faster and easier.Complete code for the example
about the example code
As an example, here is code for the
S_IN
state, when we are inside a word, with a newc
value just read:All states use similar code: a switch on the letter, so it is faster to write and manage states. Above we see the transitions to the other 3 states.
The code for
S_OVERFLOW
is similar:And this what I am trying to show. The logic of overflow is not buried inside
S_IN
and there is no tests there for skipping remaining letters. A FSM makes it easier to abstract a model.The code for each state can be developed and tested by different people.