2012-09-06 1 views
0

Donc pour un laboratoire à uni ... J'ai été mis au défi de trouver tous les mots dans le fichier usr/share/dict/linux.words en utilisant fopen, fgets etc avec chaque voyelle seulement une fois, en ordre.Trouver mot avec des voyelles dans l'ordre C

à savoir facétieuse

Jusqu'à présent, j'ai le code suivant ... mais son viciée quelque part ...

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; 

} 

Des conseils serait génial !!!

Im vraiment confus au moment ...

+0

Dans quel groupe mettriez-vous le caractère 'y'? – HonkyTonk

Répondre

1

Vous accédez à v comme s'il pointait sur un emplacement contenant un certain nombre de caractères, alors qu'en réalité, vous ne réservez qu'un seul espace char * (généralement 4 octets sur un ordinateur 32 bits et 8 octets sur un ordinateur 64 bits) :

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

Cela pourrait ou ne suffira peut-être pas pour ce que vous essayez d'y stocker; dans votre cas, le nombre de voyelles, dans un mot donné.

Dans la mesure du possible, vous devriez éviter les allocations dynamiques; dans votre cas, vous n'avez pas besoin d'eux, vous pouvez déclarer un tableau de taille fixe au lieu d'un char *:

char v[5]; 

En plus de cela, vous devez vérifier si vous avez déjà lu 5 voyelles, donc que vous ne dépassez pas la taille du tableau; si, après 5 voyelles, vous en rencontrez une autre, vous pouvez arrêter le contrôle de toute façon; le mot actuellement rencontré doit être une voyelle en double, le mot ne sera donc pas qualifié.

La façon dont vous adressez les caractères est également un problème. Vérifiez à nouveau ce que fait *: il déréférence l'expression immédiatement à droite. Dans votre cas, il faudra toujours déréférencer v, puis ajouter quelque chose (ce qui est également légal, puisque le résultat de déréférencement est un omble). Donc, si le premier caractère où v pointe est un a, le second un e, alors *v donnera 'a', (*v + 1) donnera 'b', (*v +2) donnera 'c' et ainsi de suite - vous voyez, le résultat est un ajout à la lettre a par le nombre donné; Peu importe ce qui vient après le premier personnage parce que vous n'y accédez jamais. Pour obtenir ce que vous voulez avec l'arithmétique du pointeur, vous devez utiliser une parenthèse: *(v+1) - c'est-à-dire, ajoutez 1 au pointeur v, puis déréférenciez-le. Cela donnerait le deuxième caractère dans la chaîne c commençant à v, c'est-à-dire 'e'. Notez qu'avec v déclaré comme ci-dessus, vous pouvez simplement écrire v[0], v[1], v[2] et ainsi de suite pour adresser chaque caractère. Mis à part cela, vérifiez la dernière comparaison dans votre condition if, vous avez un «e» au lieu d'un «u» là-bas. Par ailleurs, en guise de note de côté, et quelque chose à penser: Il existe une solution à votre problème qui ne nécessite pas du tout les variables v/vowel ... une seule variable entière!

0

Pourquoi all_vowels() allouer de la mémoire? Et, encore plus intéressant, pourquoi ne pas free() il?

Je suis assez sûr que all_vowels() n'a pas à allouer de la mémoire, et peut être un peu plus simple que ce que vous avez.

En outre, vous ne pouvez pas utiliser feof()avant en essayant de lire à partir du fichier. Retirez-le, bouclez simplement jusqu'à ce que fgets() renvoie NULL.

Je probablement écrire une fonction d'aide int is_vowel(char c); pour rendre le code plus clair, puis attaquer le problème comme si dans 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 
+0

'Let voyelles = voyelles [1:]' J'espère que cette ligne de pseudo-code ne fait pas penser à quelqu'un que copier une sous-chaîne de 'voyelles' est une bonne idée dans C. –

1

mais son viciée quelque part ...

Pourrait-il y avoir une erreur ici?

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

Il peut également y avoir d'autres erreurs. Je n'ai pas vérifié tout votre code.

+0

merci .... haha ​​ill check si ça marche –

+0

Ouais, c'est faux ... peu c'est pas mon problème ... –

1

Voici un grand défaut:

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

Cela alloue seulement quatre ou huit octets (selon si vous êtes sur une plate-forme 32 bits ou 64 bits). Je suppose que vous voulez un peu plus que ça.

PS. À l'avenir, vous devriez probablement essayer d'être plus précis au lieu de simplement dire que «c'est défectueux».

0

Okay .. Donc, j'ai finalement obtenu la bonne sortie ... Tous les conseils ou astuces pour une plus grande efficacité seraient très appréciés.

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; 

} 
+0

Sauf ... Je reçois des cordes avec aeiou dans l'ordre et les voyelles suivantes après cela ... ie abstemiousness –

0

peu incertain au sujet parseing votre fichier encore i fonction (s) ci-dessous vérifier qu'un caractère est une voyelle et teste si la voyelle suivante est supérieure à la voyelle actuelle.

#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

Questions connexes