【问题标题】:Find Word with Vowels in order C按 C 顺序查找带元音的单词
【发布时间】:2012-09-06 09:49:01
【问题描述】:

所以对于大学的实验室...我一直面临着在 usr/share/dict/linux.words 中找到所有单词的挑战 按顺序对每个元音使用 fopen、fgets 等进行归档。

即搞笑

到目前为止,我有以下代码......但它在某处有缺陷......

int all_vowels( char *s )
{ 
    const unsigned char *p = (const unsigned char *)s;

    char *v = malloc(sizeof(char *));
    char *vowel = v;

if(*p == '\0') return -1;

while( *p != '\0' )
{    
        if( *p == 'a' || *p =='e' || *p =='i'|| *p =='o' || *p =='u' )
        {
            *v = *p;
            v++;
        }
        p++;
    }


    if ( *vowel == 'a' && (*vowel + 1) == 'e' && (*vowel + 2) == 'i' && (*vowel + 3) ==     'o' && (*vowel + 4) == 'u' ) 
    { 
        return 1; 
    }

    return -1;
}

int main (int argc, char *argv[])
{    
    FILE *file;
    char line[BUFSIZ];

    if (( file = fopen("/usr/share/dict/words", "r") ) == NULL) 
    {
        fprintf(stderr, "cannot open %s\n", "/usr/share/dict/words");
        exit(1);
    } 

    while ( !feof(file) )
    {
        fgets(line, sizeof(line), file);
        if ( all_vowels(line) == 1 )
        {
            printf("%s\n", line);
        }
    }
    fclose(file);
    return 0;

}

任何提示都会很棒!!!

我现在真的很迷茫……

【问题讨论】:

  • 你会将角色y放入哪个组?

标签: c string fgets


【解决方案1】:

您正在访问v,就好像它指向一个包含多个字符的位置,而实际上您只为一个char * 保留空间(通常在 32 位机器上为 4 个字节,在 64 位机器上为 8 个字节)位机):

char *v = malloc(sizeof(char *));

对于您要存储的内容,这可能不够,也可能不够;在你的情况下,元音的数量,在任何给定的单词中。

应尽可能避免动态分配;在您的情况下,您不需要它们,您可以声明一个固定大小的数组而不是 char*:

char v[5];

除此之外,你必须检查你是否已经读过5个元音,这样你就不会超过数组大小;如果在 5 个元音之后遇到另一个元音,则无论如何都可以停止检查;当前遇到的必须是重复元音,因此该单词不合格。

处理字符的方式也是一个问题。再次检查* 做了什么:它立即取消引用右侧的表达式。在您的情况下,它将始终取消引用 v,然后向其添加一些内容(这也是合法的,因为取消引用的结果是一个字符)。因此,如果 v 指向的第一个字符是 a,第二个是 e,那么 *v 将产生 'a'(*v + 1) 将产生 'b'(*v +2) 将产生 'c' 等等 - 你看,结果是给定数字对字母 a 的加法;第一个字符之后的内容并不重要,因为您永远不会访问那里的值。要通过指针算术实现您想要的,您必须使用括号:*(v+1) - 即,将 1 添加到指针 v,然后取消引用它。这将产生从v 开始的c 字符串中的第二个字符,即'e'。 请注意,使用如上声明的 v,您可以简单地编写 v[0]v[1]v[2] 等来寻址每个字符。

除此之外,检查 if 条件中的最后一个比较,那里有一个 'e' 而不是 'u'。

顺便说一句,作为旁注,还有一些需要考虑的事情:有一个解决您的问题的方法,它根本不需要 v/vowel 变量...只需要一个整数变量!

【讨论】:

    【解决方案2】:

    但它有缺陷的地方......

    这里会不会有错误?

    if ( *vowel      == 'a' &&
        (*vowel + 1) == 'e' &&
        (*vowel + 2) == 'i' &&
        (*vowel + 3) == 'o' &&
        (*vowel + 4) == 'e' )      
    //                  ^^^ 'u'?
    

    可能还有其他错误。我还没有检查你所有的代码。

    【讨论】:

      【解决方案3】:

      这是一个缺陷:

      char *v = malloc(sizeof(char *));
      

      这只分配四个或八个字节(取决于您是在 32 位还是 64 位平台上)。我猜你想要的远不止这些。

      PS。将来,您可能应该尝试更具体,而不是仅仅说“它有缺陷”。

      【讨论】:

        【解决方案4】:

        为什么all_vowels() 分配内存?而且,更有趣的是,为什么不free()呢?

        我很确定all_vowels() 不必分配任何内存,并且可以比您拥有的更简单。

        此外,您不能在尝试读取文件之前使用feof()。删除它,循环直到fgets() 返回NULL

        我可能会编写一个辅助函数int is_vowel(char c); 来使代码更清晰,然后像all_vowels() 中这样解决问题:

        vowels = "aeiou"
        for each character x in the string to check:
          if is_vowel(x):
            if vowels starts with x:
              let vowels = vowels[1:]
            else
              return false
        return true if vowels is empty
        

        【讨论】:

        • let vowels = vowels[1:] 我希望这行伪代码不会让任何人认为在 C 中复制出 vowels 的子字符串是个好主意。
        【解决方案5】:

        好的..所以我终于得到了正确的输出...任何提高效率的提示或技巧将不胜感激。

        int all_vowels( char *s )
        {
        const unsigned char *p = (const unsigned char *)s;
        
        char v[5];
        int i = 0;
        if(*p == '\0') return -1;
        
        while( *p != '\0' )
        {
            if( (*p == 'a' || *p =='e' || *p =='i'|| *p =='o' || *p =='u') && ( i < 5 )        )
            {
                v[i] = *p;
                i++;
            }
            p++;
        }
        
        
        if ( ( v[0] == 'a'  &&  v[1] == 'e'  &&  v[2] == 'i'  &&  v[3] == 'o'  &&  v[4] == 'u' ) && (strlen(v) == 5 )) 
        { 
            return 1; 
        }
        
        return -1;
        }
        
        int main (int argc, char *argv[])
        {
        FILE *file;
        char line[30];
        
        if (( file = fopen("/usr/share/dict/words", "r") ) == NULL) 
        {
            fprintf(stderr, "cannot open %s\n", "/usr/share/dict/words");
            exit(1);
        } 
        
        while ( fgets(line, sizeof(line), file) )
        {
        
            if ( all_vowels(line) == 1 )
            {
                printf("%s\n", line);
            }
        }
        fclose(file);
        return 0;
        
        }
        

        【讨论】:

        • 除了...我正在按顺序获取带有 aeiou 的字符串,然后是随后的元音...即节制
        【解决方案6】:

        关于解析你的文件有点不确定,但我下面的函数检查一个字符是否是元音并测试下一个元音是否大于当前元音。

        #include <stdio.h>
        
        // for readability not advocating the 
        // usage of #define booleans etc
        #define TRUE  1
        #define FALSE 0
        
        int isVowel (char c)
        {
            switch (c)
            {
                case 'a': return TRUE;
                case 'e': return TRUE;
                case 'i': return TRUE;
                case 'o': return TRUE;
                case 'u': return TRUE;
                case 'A': return TRUE;
                case 'E': return TRUE;
                case 'I': return TRUE;
                case 'O': return TRUE;
                case 'U': return TRUE;
            }
        
            return FALSE;
        }
        
        int hasOrderedVowels (char *str)
        {    
            char c1, c2;
        
            c1 = *str;
            c2 = *(++str);
        
            // ignore words beginning in vowels other then 'a' or 'A'
            if (isVowel(c1) && !(c1 == 'a' || c1 == 'A')) return FALSE;
        
            do {
                // ignore case of `c1`
                if (c1 >= 'a')
                    c1 -= 32;
        
                // ignore case of `c2`
                if (c2 >= 'a')
                    c2 -= 32;
        
                // compare vowels and increment
                // pointers as appropriate
                if (isVowel(c1) && isVowel(c2))
                {
                    // if we have found a vowel less then or equal to current
                    // then they are not in order/more then one, if we have found
                    // a 'U' and there are more vowels then this would be a duplicate
                    if (c2 <= c1 || c1 == 'U')
                        return FALSE;
        
                    c1 = c2;
                } 
                else if (isVowel(c2))    // found first vowel so assign to c1
                {
                    if (!(c1 == 'a' || c1 == 'A'))
                    {
                        return FALSE;
                    }
                    c1 = c2;
                }
                else if (!isVowel(c1))   
                {
                    c1 = *(str += 2);    // skip over c2
                }
                c2 = *(++str); 
            } 
            while (c2 != '\0');
        
            return (c1 == 'U');
        }
        
        int main ()
        {
            char *str[] = {"aeiou", "facecious", "chimpanze", "baboon"};
            int i = 0;
        
            for (; i<5; i++)
            {
                printf ("%s: %i\n", str[i], hasOrderedVowels(str[i]));
            }
        
            return 0;
        }
        

        demo

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-08-17
          • 1970-01-01
          • 1970-01-01
          • 2016-03-09
          • 1970-01-01
          • 2022-01-15
          • 2021-08-12
          相关资源
          最近更新 更多