0

したがって、大学のラボでは... usr / share / dict / linux.wordsファイル内のすべての単語を、fopen、fgetsなどを使用してすべての母音を順番に1回だけ検索するように求められました。

すなわちファセット

これまでのところ、次のコードがあります...しかし、どこかに欠陥があります...

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;

}

どんなヒントも素晴らしいでしょう!!!

私は今本当に混乱しています...

4

6 に答える 6

1

しかし、どこかに欠陥があります...

ここでエラーが発生する可能性がありますか?

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

他のエラーもある可能性があります。すべてのコードをチェックしていません。

于 2012-09-06T09:51:17.993 に答える
1

ここに大きな欠陥があります:

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

これにより、4バイトまたは8バイトのみが割り当てられます(32ビットまたは64ビットのプラットフォームを使用しているかどうかによって異なります)。それよりもう少し欲しいと思います。

PS。将来的には、単に「欠陥がある」と言うのではなく、より具体的にする必要があります。

于 2012-09-06T09:52:23.803 に答える
1

実際に1つのシングル用のスペースのみを予約している場合(通常、32ビットマシンでは4バイト、64ビットマシンでは8バイト)v、多くの文字を保持している場所を指しているかのようにアクセスしています。char *

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

それはあなたがそれに保存しようとしているものにとって十分かもしれないし、そうでないかもしれません。あなたの場合、任意の単語での母音の数。

可能な限り、動的な割り当ては避けてください。あなたの場合、それらは必要ありません。char*の代わりに固定サイズの配列を宣言できます。

char v[5];

それに加えて、配列サイズを超えないように、すでに5つの母音を読んだかどうかを確認する必要があります。5つの母音の後で別の母音に遭遇した場合は、とにかくチェックを停止できます。現在遭遇している母音は重複母音である必要があるため、その単語は修飾されません。

文字のアドレス指定方法も問題です。何をするかをもう一度確認してください*。式をすぐ右に逆参照します。あなたの場合、それは常にvを逆参照し、それから何かを追加します(逆参照の結果はcharなので、これも合法です)。したがって、vが指す最初の文字がaである場合、2番目のeは、*vを生成'a'し、(*v + 1)を生成し'b'(*v +2)を生成'c'します。そこの値にアクセスすることは決してないので、最初の文字の後に何が来るかはまったく問題ではありません。ポインタ演算で目的を達成するには、括弧を使用する必要があります。-*(v+1)つまり、ポインタに1を追加します。v、次にそれを逆参照します。これにより、c文字列の2番目の文字が-で始まりvます'e'。上記のようにvを宣言すると、、、などを記述して各文字をアドレス指定できることに注意してv[0]ください。v[1]v[2]

それとは別に、if条件の最後の比較を確認してください。そこには、「u」ではなく「e」があります。

ちなみに、補足として、そして考えるべきことがあります:v/vowel変数をまったく必要としない問題の解決策があります...単一の整数変数のみです!

于 2012-09-06T09:52:52.740 に答える
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
于 2012-09-06T09:50:49.080 に答える
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;

}
于 2012-09-06T11:23:58.383 に答える
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;
}

デモ

于 2012-09-06T14:57:48.140 に答える