C 数组中音节的计数

C 数组中音节的计数,c,C,我试图计算传入数组的字符串中每个单词的所有音节 一个音节计为两个相邻的元音(A、e、i、o、u、y)。例如,“peel”中的“ee”算作一个音节。但是,“突出”中的“u”和“e”算作两个音节。单词末尾的“e”不算作音节。此外,即使前面的规则不适用,每个单词至少有一个音节 我有一个文件,其中包含一个大字符串(字、空格和换行符),我将其传递到数组中。 我的代码通过计算单词和换行符之间的空白来计算每个单词。见下文: for (i = 0; i < lengthOfFile; i++) {

我试图计算传入数组的字符串中每个单词的所有音节

一个音节计为两个相邻的元音(A、e、i、o、u、y)。例如,“peel”中的“ee”算作一个音节。但是,“突出”中的“u”和“e”算作两个音节。单词末尾的“e”不算作音节。此外,即使前面的规则不适用,每个单词至少有一个音节

我有一个文件,其中包含一个大字符串(字、空格和换行符),我将其传递到数组中。 我的代码通过计算单词和换行符之间的空白来计算每个单词。见下文:

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
或使用POSIX
getline
执行相同的操作,或者使用
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
或使用POSIX
getline
执行相同的操作,或者使用
fseek/ftell
stat
一次性分配所有文件,然后
fread
在一次调用中将整个文件分配到一个缓冲区——由您决定)

内存使用/错误检查

在您编写的任何动态分配内存的代码中,对于所分配的任何内存块,您有两个责任:(1)始终保留指向内存块起始地址的指针,以便(2)在不再需要它时可以释放它

必须使用内存错误检查程序,以确保您不会试图访问内存或写入超出/超出分配的块的边界,尝试在未初始化的值上读取或建立条件跳转,最后确认释放所有已分配的内存