我编写了一个程序,最多可以包含100个单词,并将它们存储在一个数组中。然后计算单词的平均长度并将结果打印到stderr。我的程序在我的所有测试脚本上工作正常,除了一个,在给定的测试脚本中,平均值计算为4.04,但我需要它为4.02。我不确定为什么我的答案不够准确? 干杯
计划 -
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void *emalloc(size_t s) {
void *result = malloc(s);
if (NULL == result) {
fprintf(stderr, "Memory allocation failed!\n");
exit(EXIT_FAILURE);
}
return result;
}
/* n is the size of the array */
void print_array(char **a, int n, double average) {
if (n == 0) {
/* do nothing */
} else {
if (strlen(a[0]) > average) {
fprintf(stdout, "%s\n", a[0]);
}
print_array(a + 1, n - 1, average);
}
}
int main()
{
#define SIZE 100
char *username[100];
char word[80];
int num_words = 0;
int p;
float average = 0.0;
/* Read words into array */
while(1 == scanf("%s", word)) {
username[num_words] = emalloc((strlen(word) + 1) * sizeof(word[0]));
strcpy(username[num_words], word);
num_words++;
}
/* Print out array */
for (p = 0; p < num_words; p++) {
average += strlen(username[p]);
}
average = average / num_words;
print_array(username, num_words, average);
if (average > 0) {
fprintf(stderr, "%.2f\n", average);
}
return EXIT_SUCCESS;
}
单词的测试文件 -
hello
hi there
The quick brown fox jumps over the lazy dog
Mary had a little lamb
Little lamb little lamb
Mary had a little lamb
Its fleece was white as snow
Everywhere that Mary went
Mary went, Mary went
Everywhere that Mary went
The lamb was sure to go
It followed her to school one day
School one day, school one day
It followed her to school one day
Which was against the rules
It made the children laugh and play
Laugh and play, laugh and play
It made the children laugh and play
To see a lamb in school
答案 0 :(得分:4)
您在字长总计中包含标点符号(例如{“1}},以”Mary goes“开头)。
这足以甩掉你的结果。
您可以使用C标准库函数,
消除此类字符。
另请注意,您可能会遇到未定义的行为:在读取单词时,您可能会溢出内存缓冲区。也可能在此处起作用。为什么不计算运行平均值:根本不需要存储单词?
答案 1 :(得分:2)
继续我的评论,你有几个方面你可以删除不需要的代码,以及你需要添加检查的区域,以确保你没有添加更多的单词而不是你有指针来保持或读取更多的字符而不是你的存储空间。
例如,您绝不应尝试在num_words
数组中读取超过username
的内容,并且应将每次读取的字符数限制为SIZE - 1
个字符。你可以用:
/* Read words into array */
while (num_words + 1 < SIZE && 1 == scanf (" %99s", word)) {
要为每个单词分配存储空间,您只需要:
size_t len = strlen (word);
username[num_words] = emalloc (len + 1);
您可能还会发现让单词长度保持正常sum
并完全消除p
会更方便。
num_words++;
sum += len;
避免在同一系列计算中混合使用double
和float
类型,
只需设置average
(和sum
)类型double
。
将这些部分组合在一起,您可以重写main()
,类似于以下内容:
int main (void)
{
char *username[SIZE],
word[SIZE];
int num_words = 0;
double sum = 0.0,
average = 0.0;
/* Read words into array */
while (num_words + 1 < SIZE && 1 == scanf (" %99s", word)) {
size_t len = strlen (word);
username[num_words] = emalloc (len + 1);
if (!username[num_words]) {
fprintf (stderr, "error: memory exhausted, username[%d]\n",
num_words);
exit (EXIT_FAILURE);
}
strcpy (username[num_words], word);
num_words++;
sum += len;
}
average = sum / num_words;
print_array (username, num_words, average);
if (average > 0) {
fprintf(stderr, "%.2f\n", average);
}
return EXIT_SUCCESS;
}
示例使用/输出
使用输入文件:
$ ./bin/words_avg_len <../dat/wcwords.txt
hello
there
quick
brown
jumps
little
Little
little
little
fleece
white
Everywhere
went,
Everywhere
followed
school
School
school
followed
school
Which
against
rules
children
laugh
Laugh
play,
laugh
children
laugh
4.02
(注意: 4.02
确实包含两个逗号)
根据讨论,根本不需要将单词存储在数组中来计算从输入读取的字符串的平均长度。唯一关键的数据是每个单词的长度和从中获取长度的单词数。
在这种情况下,您可以将代码显着缩短为类似于以下内容:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100
int main (void)
{
char word[SIZE];
int num_words = 0;
double sum = 0.0,
average = 0.0;
/* Read words into array */
while (num_words + 1 < SIZE && 1 == scanf (" %99s", word)) {
sum += strlen (word);
num_words++;
}
average = sum / num_words;
if (average > 0) {
fprintf(stderr, "average: %.2f\n", average);
}
return EXIT_SUCCESS;
}
示例使用/输出
$ ./bin/words_avg_len_nosave <../dat/wcwords.txt
average: 4.02
(这样可以减少错误:)
答案 2 :(得分:-1)
解决方案:我运行的脚本包含101个单词,该数组只能存储100个。