2012-02-21 20 views
2

J'ai une fonction qui prend un nom de fichier (chaîne) et je veux avoir un tableau de noms de fichiers (chaînes) pour vérifier si le nom de fichier taht a été passé dans le tableau et sinon l'ajouter. Voici ce que j'ai obtenu jusqu'ici.Recherche d'une chaîne dans un tableau de chaînes dans C

bool read_file(char * filename, bool warnings){ 
    //Check to see if filename is in array files 
    static char * files[MAXFILES]; 
    static int counter = 0; 
    for(int i=0;i<counter;i++){ 
    if(strcmp(filename,files[i]) == 0){ 
     fprintf(stdout, "Error\n"); 
     return 0; 
    } 
    else{ 
     files[counter]=filename; 
     counter++; 
    } 
    } 
    FILE * fp = fopen(filename,"r"); 
    if(fp == NULL){ 
    if(warnings){ 
     fprintf(stderr, "Can't open the file %s\n",filename); 
     return 0; 
    } 
    else{ 
     return 0; 
    } 
    } 
    else{ 
    fclose(fp); 
    fp = NULL; 
    return 1; 
    } 
} 

Pour une raison quelconque, il ne va pas ajouter de noms de fichiers aux fichiers [] toute aide serait appricated.

+0

La boucle 'for' n'est jamais entrée, vous initialisez' counter' à '0' et vous utilisez' i Naveen

+0

Pourquoi 'counter' et' files' doivent-ils être statiques? – Lundin

Répondre

1

Jetez un oeil à la première fois à travers votre boucle (quand i == 0 et counter == 0):

static int counter = 0; 
for(int i = 0; i < counter; i++) { 
    // this never runs 
} 

i < counter est toujours faux, parce que counter est incrémentée dans le corps de la boucle.

Vous devrez repenser votre logique. Cette fonction fait beaucoup de choses. Peut-être quelque chose comme ça en face de la boucle contribuera:

if (counter == 0) { 
    // first time in the function, just add the filename 
    files[counter]=filename; 
    counter++; 
} 
else { 
    for (int i = 0; i < counter; i++) { 
     ... 
    } 
} 

Cependant, vous pourriez avoir une meilleure séparation de chance cela en un couple fonctionne. À ajouter un nom de fichier au tableau, un autre pour vérifier si elle est déjà là, un troisième pour ouvrir le fichier, etc.

+0

+ 1 pour fractionner la fonction - quand le premier commentaire d'une fonction ne semble pas correspondre au nom de la fonction, c'est probablement le bon moment pour la diviser :) –

+0

Boîtier spécial la première itération n'est pas très soignée et bien rangé. Mais je suis d'accord avec la suggestion de diviser la fonction en plus petits morceaux. A +1 et -1 laisse un net aucun changement. –

+0

@JonathanLeffler - Oui, le problème principal est que la portée de la fonction est beaucoup trop grande (et cela veut vraiment être une classe). Spécial-enveloppe la variable 'counter' est le hack rapide pour permettre le temps pour un refactoring correct: D – Seth

0

changer votre boucle à

for (i=0;i<=counter;i++) 
+0

Non; c'est parfois, mais très rarement, un bon moyen d'écrire une boucle en C. La boucle 'for (i = 0; i

1

Regardez la clause else de cette boucle :

for(int i=0;i<counter;i++){ 
    if(strcmp(filename,files[i]) == 0){ 
     fprintf(stdout, "Error\n"); 
     return 0; 
    } 
    else{ 
     files[counter]=filename; 
     counter++; 
    } 
    } 

vous voulez ajouter le fichier à la liste une seule fois que vous savez qu'il est pas dans la liste, et vous ne saurez pas que jusqu'à ce que vous avez traversé toute la liste. Donc, ce code devrait probablement ressembler à:

for (int i = 0; i < counter; i++) 
{ 
    if (strcmp(filename, files[i]) == 0) 
    { 
     fprintf(stdout, "Duplicate file %s found at %d\n", filename, i); 
     return 0; 
    } 
} 
files[counter++] = filename; 

Notez le meilleur message d'erreur que juste 'Erreur'. Vous aurez besoin de savoir ce qui n'a pas fonctionné car ce ne sera pas le seul endroit du programme où il pourrait y avoir des erreurs. Vous pouvez débattre si le nombre est utile; le nom le plus certainement est, mais ayant le numéro d'index pourrait vous aider aussi.

1

Votre else est égaré. Ce:

for(int i=0;i<counter;i++){ 
    if(strcmp(filename,files[i]) == 0){ 
     fprintf(stdout, "Error\n"); 
     return 0; 
    } 
    else{ 
     files[counter]=filename; 
     counter++; 
    } 
} 

ne sera plus jamais entré, et il était d'être, il pense toujours que le dossier était dans la liste, parce que vous ajoutez avant de terminer la vérification. Vous trouverez alors celui que vous avez ajouté, et pensez qu'il était déjà là.

Au lieu de cela, attendez jusqu'à ce que vous avez terminé la vérification de toute la liste jusqu'à ce que vous ajoutez le nom du fichier:

for(int i=0;i<counter;i++){ 
    if(strcmp(filename,files[i]) == 0){ 
    fprintf(stdout, "Error\n"); 
    return 0; 
    } 
} 
files[counter]=filename; 
counter++; 

La clé est que le return 0 redirige le flux de votre fonction, plutôt que d'une clause else. Vous savez que tant que la boucle se termine et que vous êtes toujours dans la fonction que le nom de fichier n'est pas encore là.

Questions connexes