按顺序C用元音查找单词

时间:2012-09-06 09:49:02

标签: c string fgets

所以对于uni的实验室...我一直被挑战找到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;

}

任何提示都会很棒!!!

我现在真的很困惑......

6 个答案:

答案 0 :(得分:1)

  

但它在某处有缺陷...

这里可能有错误吗?

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

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

答案 1 :(得分:1)

这是一个缺陷:

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

这仅分配四个或八个字节(取决于您是在32位还是64位平台上)。我猜你想要多一点。

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

答案 2 :(得分:1)

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

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

这可能会或者可能不足以满足您试图存储的内容;在你的情况下,任何给定单词中的元音数量。

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

char v[5];

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

解决角色的方式也是一个问题。再次检查*的作用:它会立即将表达式取消引用到右侧。在你的情况下,它总是取消引用v,然后添加一些东西(这也是合法的,因为解除引用的结果是一个char)。因此,如果v指向的第一个字符是a,第二个字符是e,那么*v将产生'a'(*v + 1)将产生'b'(*v +2)会产生'c'等等 - 你看,结果是给定数字加上字母a;在第一个角色之后发生什么并不重要,因为你永远不会在那里访问它。要使用指针运算实现所需,您必须使用括号:*(v+1) - 即将指针v加1,然后取消引用它。这将产生从v开始的c字符串中的第二个字符,即'e'。 请注意,使用上面声明的v,您只需编写v[0]v[1]v[2]等等即可解决每个字符的问题。

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

顺便提一下,作为旁注,需要考虑的事项:您的问题有一个解决方案,根本不需要v / vowel个变量...只有一个整数变量!

答案 3 :(得分:0)

为什么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

答案 4 :(得分:0)

好的..所以我终于得到了正确的输出......非常感谢提高效率的任何提示或提示。

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;

}

答案 5 :(得分:0)

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

#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