C 数组中音节的计数
我试图计算传入数组的字符串中每个单词的所有音节 一个音节计为两个相邻的元音(A、e、i、o、u、y)。例如,“peel”中的“ee”算作一个音节。但是,“突出”中的“u”和“e”算作两个音节。单词末尾的“e”不算作音节。此外,即使前面的规则不适用,每个单词至少有一个音节 我有一个文件,其中包含一个大字符串(字、空格和换行符),我将其传递到数组中。 我的代码通过计算单词和换行符之间的空白来计算每个单词。见下文:C 数组中音节的计数,c,C,我试图计算传入数组的字符串中每个单词的所有音节 一个音节计为两个相邻的元音(A、e、i、o、u、y)。例如,“peel”中的“ee”算作一个音节。但是,“突出”中的“u”和“e”算作两个音节。单词末尾的“e”不算作音节。此外,即使前面的规则不适用,每个单词至少有一个音节 我有一个文件,其中包含一个大字符串(字、空格和换行符),我将其传递到数组中。 我的代码通过计算单词和换行符之间的空白来计算每个单词。见下文: for (i = 0; i < lengthOfFile; i++) {
for (i = 0; i < lengthOfFile; i++)
{
if (charArray[i] == ' ' || charArray[i] == '\n')
{
wordCount++;
}
}
(i=0;i
{
if(charArray[i]=''| charArray[i]='\n')
{
字数++;
}
}
其中,charArray
是传递到数组中的文件(freads)
,lengthOfFile
是由(fseek)
计算的文件中的总字节数,wordCount
是计算的总字数
从这里开始,我需要以某种方式计算数组中每个单词的音节,但不知道从哪里开始。如果您仍然有问题,那只是因为您过度思考了问题。无论何时你在计数、确定频率等等,你通常都可以通过使用“状态循环”来简化事情。状态循环只不过是一个循环,在其中循环每个字符(或任何字符),并处理您发现自己处于的任何状态,如:
- 我读过字吗?(如果不是,则处理该状态)李>
- 当前角色是空格吗?(如果是这样,为简单起见,假设没有多个空格,则表示您已到达一个单词的结尾,请处理该状态)李>
- 当前字符是否为非空格和非元音?(如果是,如果我的最后一个字符是元音,增加我的音节计数);及
- 无论当前字符的分类如何,我都需要做什么?(输出它,最后设置=电流等)
“my”
和“he”
这样的单词在到达单词末尾时,通过检查您的音节计数是否为零,被算作单个音节
总而言之,您可以编写一个基本实现,如:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main (void) {
char c, last = 0; /* current & last char */
const char *vowels = "AEIOUYaeiouy"; /* vowels (plus Yy) */
size_t syllcnt = 0, totalcnt = 0; /* word syllable cnt & total */
while ((c = getchar()) != EOF) { /* read each character */
if (!last) { /* if 1st char (no last) */
putchar (c); /* just output it */
last = c; /* set last */
continue; /* go get next */
}
if (isspace (c)) { /* if space, end of word */
if (!syllcnt) /* if no syll, it's 1 (he, my) */
syllcnt = 1;
printf (" - %zu\n", syllcnt); /* output syll cnt and '\n' */
totalcnt += syllcnt; /* add to total */
syllcnt = 0; /* reset syllcnt to zero */
} /* otherwise */
else if (!strchr (vowels, c)) /* if not vowel */
if (strchr (vowels, last)) /* and last was vowel */
syllcnt++; /* increment syllcnt */
if (!isspace (c)) /* if not space */
putchar (c); /* output it */
last = c; /* set last = c */
}
printf ("\n total syllables: %zu\n", totalcnt);
}
如果您需要从文件中读取单词,只需将文件作为输入重定向到stdin
上的程序,例如
./syllablecnt < inputfile
(您可以使用fgets
或使用POSIXgetline
执行相同的操作,或者使用fseek/ftell
或stat
一次性分配所有文件,然后fread
在一次调用中将整个文件分配到一个缓冲区——由您决定)
内存使用/错误检查
在您编写的任何动态分配内存的代码中,对于所分配的任何内存块,您有两个责任:(1)始终保留指向内存块起始地址的指针,以便(2)在不再需要它时可以释放它
必须使用内存错误检查程序,以确保您不会试图访问内存或写入超出/超出分配的块的边界,尝试在未初始化的值上读取或建立条件跳转,最后确认释放所有已分配的内存
对于Linux,valgrind
是正常的选择。每个平台都有类似的内存检查器。它们都很容易使用,只需运行程序即可
$ valgrind ./bin/syllablecnt_array dat/syllables.txt
==19517== Memcheck, a memory error detector
==19517== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==19517== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==19517== Command: ./bin/syllablecnt_array dat/syllables.txt
==19517==
my - 1
dog - 1
eats - 1
banannas - 3
he - 1
peels - 1
while - 1
getting - 2
juked - 2
total syllables: 13
==19517==
==19517== HEAP SUMMARY:
==19517== in use at exit: 0 bytes in 0 blocks
==19517== total heap usage: 5 allocs, 5 frees, 672 bytes allocated
==19517==
==19517== All heap blocks were freed -- no leaks are possible
==19517==
==19517== For counts of detected and suppressed errors, rerun with: -v
==19517== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认已释放所有已分配的内存,并且没有内存错误
仔细检查一下,如果你还有其他问题,请告诉我。如果你仍然有问题,那只是因为你想得太多了。无论何时你在计数、确定频率等等,你通常都可以通过使用“状态循环”来简化事情。状态循环只不过是一个循环,在其中循环每个字符(或任何字符),并处理您发现自己处于的任何状态,如:
- 我读过字吗?(如果不是,则处理该状态)李>
- 当前角色是空格吗?(如果是这样,为简单起见,假设没有多个空格,则表示您已到达一个单词的结尾,请处理该状态)李>
- 当前字符是否为非空格和非元音?(如果是,如果我的最后一个字符是元音,增加我的音节计数);及
- 无论当前字符的分类如何,我都需要做什么?(输出它,最后设置=电流等)
“my”
和“he”
这样的单词在到达单词末尾时,通过检查您的音节计数是否为零,被算作单个音节
总而言之,您可以编写一个基本实现,如:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main (void) {
char c, last = 0; /* current & last char */
const char *vowels = "AEIOUYaeiouy"; /* vowels (plus Yy) */
size_t syllcnt = 0, totalcnt = 0; /* word syllable cnt & total */
while ((c = getchar()) != EOF) { /* read each character */
if (!last) { /* if 1st char (no last) */
putchar (c); /* just output it */
last = c; /* set last */
continue; /* go get next */
}
if (isspace (c)) { /* if space, end of word */
if (!syllcnt) /* if no syll, it's 1 (he, my) */
syllcnt = 1;
printf (" - %zu\n", syllcnt); /* output syll cnt and '\n' */
totalcnt += syllcnt; /* add to total */
syllcnt = 0; /* reset syllcnt to zero */
} /* otherwise */
else if (!strchr (vowels, c)) /* if not vowel */
if (strchr (vowels, last)) /* and last was vowel */
syllcnt++; /* increment syllcnt */
if (!isspace (c)) /* if not space */
putchar (c); /* output it */
last = c; /* set last = c */
}
printf ("\n total syllables: %zu\n", totalcnt);
}
如果您需要从文件中读取单词,只需将文件作为输入重定向到stdin
上的程序,例如
./syllablecnt < inputfile
(您可以使用fgets
或使用POSIXgetline
执行相同的操作,或者使用fseek/ftell
或stat
一次性分配所有文件,然后fread
在一次调用中将整个文件分配到一个缓冲区——由您决定)
内存使用/错误检查
在您编写的任何动态分配内存的代码中,对于所分配的任何内存块,您有两个责任:(1)始终保留指向内存块起始地址的指针,以便(2)在不再需要它时可以释放它
必须使用内存错误检查程序,以确保您不会试图访问内存或写入超出/超出分配的块的边界,尝试在未初始化的值上读取或建立条件跳转,最后确认释放所有已分配的内存