gpt4 book ai didi

C 计算字符串中 n 长度单词的出现次数

转载 作者:行者123 更新时间:2023-11-30 17:01:47 24 4
gpt4 key购买 nike

新来的,正在寻求一些帮助。尝试自学 C 并在网上找到了一些作业。 ( https://www.cs.cf.ac.uk/Dave/C/node7.html ) 基本上只是试图通过仅查找一个 n 长度的单词而不是多个单词来创建该作业的一部分(练习 12337)。我的程序现在计算单词总数,但我不知道如何超越该点来开始根据单词的长度挑选单词。

#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>

int words(const char lne[ ]);

int main()
{
char lne[60], name[25]="";
FILE *fp;

printf("Enter name of the input file: ");
scanf("%s", &name);

if ((fp = fopen(name, "r")) == NULL)
{
printf("File cannot be opened!");
}

else
{
int cntf=-1, cntw=-1;
while (fgets(lne, sizeof lne, fp))
cntf += words(lne);
//cntw += letter(lne);
printf("\nThe most frequent word length is %d", cntf );
printf("\nThe message includes %d words of that length", cntf);


fclose(fp);
}

return 0;
}

int words(const char lne[])
{
int i, count=0;
for (i=0; i<strlen(lne); i++)
{
if (lne[i] == ' '||lne[i] == '\t'||lne[i] == '\n')
count++;
}
return count;
}

最佳答案

当测量某个范围内任何出现的频率(字长、字符出现等)时,一种非常简单的方法是声明一个数组,该数组至少包含该范围内的最大元素数(例如,如果您如果要计算 a-z 出现的次数,则需要一个至少包含 26 元素的数组)。 (对于单词长度,您需要一个至少为 27 的数组——未删节字典中最长单词的长度)。如果范围不确定,您始终可以包含一些额外的元素,以确保覆盖该范围。

数组必须初始化为0。然后,对于每次出现的情况,继续使用 a-z 示例,每次遇到 a 时,您都会增加与 a 关联的索引(例如 0b=1c=2)等等。因此,当遇到 a 且您的数组名称为 charfreq 时,您将递增

charfreq[0]++;

读取所有字符并递增关联索引后,charfreq[0] 中的值就是 a 的数量,charfreq[1 ] b 的数量,依此类推。

您也可以使用这种精确的方法来收集字号大小的频率。当然,在找到长度的频率之前,您必须找到单词的数量。虽然您可以通过计算每行的空白分隔符并添加 1 来手动查找单词数,但这并不能让您获得每个单词的长度(您可以沿着字符串向下移动 2 个指针,如下所示)您计算每个单词后终止/恢复的空格并获取指针差异),但 C 库具有 strtok 来帮助您标记该行。

当您对行进行标记时(无论您如何操作),您只需获取每个标记(单词)的长度并更新您的频率数组 - 就完成了。您的 words 函数可以在 strtok 的帮助下编写如下(注意 strtok 修改原始字符串,因此如果您必须保留原件)

int words (const char *buf, const char *delims, int *freq)
{
char tmp[MAXC] = ""; /* temp array to hold buf as */
char *p; /* strtok modifies original */
int cnt = 0;

strncpy (tmp, buf, sizeof tmp); /* copy buf to tmp & tokenize */
for (p = strtok (tmp,delims); p; p = strtok (NULL, delims)) {
cnt++;
freq[strlen(p)]++;
}

return cnt;
}

将这些部分放在一起,注意文件名通常作为参数传递,您可以执行如下操作来从文件(或默认情况下从 stdin)读取/处理单词:

#include <stdio.h>
#include <string.h>

enum { MAXF = 32, MAXC = 256 };

int words (const char *buf, const char *delims, int *freq);

int main (int argc, char **argv) {

char buf[MAXC] = "";
char *delims = " ,.\t\n"; /* delimiters for strtok */
int cntw = 0, i, midx = 0, mfreq = 0;
int freq[MAXF] = {0};
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

if (!fp) { /* validate file is open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}

while (fgets (buf, sizeof buf, fp)) /* read each line */
cntw += words (buf, delims, freq); /* call words */

i = MAXF;
while (i--) /* find longest most frequent length */
if (freq[i] > mfreq) { /* in mfreq, which occurs at */
mfreq = freq[i]; /* midx - most frequent idx */
midx = i;
}

/* output results */
printf (" \n There are '%d' words in the file.\n", cntw);
printf (" The most frequent word length is '%d'\n", midx);
printf (" The message includes '%d' words of that length.\n\n",
mfreq);

if (fp != stdin) fclose (fp); /* close file if not stdin */

return 0;
}

int words (const char *buf, const char *delims, int *freq)
{
char tmp[MAXC] = ""; /* temp array to hold buf as */
char *p; /* strtok modifies original */
int cnt = 0;

strncpy (tmp, buf, sizeof tmp); /* copy buf to tmp & tokenize */
for (p = strtok (tmp,delims); p; p = strtok (NULL, delims)) {
cnt++;
freq[strlen(p)]++;
}

return cnt;
}

输入文件示例

$ cat ../dat/captnjack.txt
This is a tale
Of Captain Jack Sparrow
A Pirate So Brave
On the Seven Seas.

示例使用/输出

$ ./bin/wordsmfreq <../dat/captnjack.txt

There are '16' words in the file.
The most frequent word length is '4'
The message includes '4' words of that length.

使用strcspn代替strtok

库中还有另一个值得使用的函数,strcspn。它将扫描字符串以查找未包含在分隔符中的事件。它返回不包含 delims 列表中任何拒绝字符的初始段的长度。您可以使用该函数重复调用 tmp,同时将指针移过 tmp 来完成 strtok 的操作。 (无需调用 strlen)

查看示例,如果您有任何疑问,请告诉我。

关于C 计算字符串中 n 长度单词的出现次数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36819814/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com