2010-03-05 4 views
0

J'ai ce code pour ouvrir plusieurs fichiers un à la fois qui est donné à la ligne de commande, puis s'il ne peut pas ouvrir l'un des fichiers, il ferme tous les fichiers et quitte.Ouverture de plusieurs fichiers en C++

/* Opens an array of files and returns a pointer to the first 
* element (the first file). 
*/ 
ifstream *OpenFiles(char * const fileNames[], size_t count) 
{ 
    /* If no command line arguments, error and exit */ 
    if (count == 0) { 
     cerr << "Invalid number of arguments."; 
     exit(EXIT_FAILURE); 
    } 
    ifstream *fileObj; 
    fileObj = new ifstream[count]; 

    if (fileObj == NULL) { 
     cerr << "Failed to create space for files"; 
     exit(EXIT_FAILURE); 
    } 

    /* Opens one file at a time and closes all files if there is an 
    * error opening any file. 
    */ 
    for (int loopCount = 0; loopCount < (int)count; loopCount++) { 
     fileObj[loopCount].open(fileNames[loopCount], ios::out); 
     if (!fileObj[loopCount].is_open()) { 
      cerr << "Failed to open " << fileNames[loopCount] << "\n"; 
      for (; loopCount >= 0; loopCount--) { 
       fileObj[loopCount].close(); 
       cout << "Closed " << fileNames[loopCount] << "\n"; 
      } 
      delete[] fileObj; 
     } 
    } 
    return fileObj; 
} 

Je fais cela pour les devoirs et mon professeur a un autre vérificateur que nous devons soumettre et me donne ces types d'avertissements:

Assign8_1.cpp(44): error 445: (Warning -- Reuse of for loop variable 'loopCount' at 'line 40' could cause chaos) 
    return fileObj; 
Assign8_1.cpp(51): error 850: (Info -- for loop index variable 'loopCount' whose type category is 'integral' is modified in body of the for loop that began at 'line 40') 
    return fileObj; 
Assign8_1.cpp(51): error 449: (Warning -- Pointer variable 'fileObj' previously deallocated [Reference: file Assign8_1.cpp: lines 30, 48]) 
Assign8_1.cpp(30): error 831: (Info -- Reference cited in prior message) 
Assign8_1.cpp(48): error 831: (Info -- Reference cited in prior message) 
} 
Assign8_1.cpp(63): error 818: (Info -- Pointer parameter 'files' (line 55) could be declared as pointing to const) 
} 

à partir du premier avertissement, je me demandais pourquoi je ne devrait pas utiliser ma variable loopCount deux fois comme je le fais dans mon code. C'était ainsi que je pensais que cela fonctionnerait, en gardant la trace du fichier que je regarde, en l'ouvrant et en le fermant de façon appropriée.

Est-ce que quelqu'un sait ce que l'erreur 449 signifie? Merci.

+0

Pour les curieux, cette sortie semble provenir d'un des outils de peluches Gimpel. –

Répondre

4

Vous devez exit(EXIT_FAILURE) après avoir delete[] fileObj dans la boucle, sinon vous simplement écraser sur la prochaine itération. C'est peut-être ce que l'avertissement 449 vous dit.

Autre que cela, le code semble bien. Si vous voulez le compiler sans ces avertissements, vous pouvez transformer la boucle interne en une boucle for-standard qui utilise uniquement loopCount comme limite. Quelque chose comme:

for (int i = loopCount; i >= 0; i--) { 
    fileObj[i].close(); 
    cout << "Closed " << fileNames[i] << "\n"; 
} 
+1

Mieux vaut faire i = 0 à i <= loopCount, car si vous utilisez un type numérique non signé (tel que std :: size_t), il s'enroulera et bouclera pour toujours. C'est une bonne habitude de toujours monter. –

+0

Merci pour le conseil, @ Michael. J'ai d'abord appris le Java, alors j'oublie souvent de penser aux types de données non signés. –

2

Vous pouvez absolument utiliser votre variable loopCount de cette façon, mais cela vous causera un bug. Au premier coup d'œil, on dirait que ça va tourner pour toujours, parce que vous ne sortez jamais de la boucle externe de la boucle intérieure. Vous décrémentez loopCount dans la boucle interne et l'incrémentez dans la boucle externe, d'avant en arrière, d'avant en arrière. Bien que l'utilisation d'un loopCounter dans une boucle interne ne soit pas une violation du langage, cela indique généralement que quelque chose se passe n'est pas ce que vous vouliez vraiment.

Vous seriez mieux en utilisant le code comme ceci:

list<ifstream> files; 

ifstream file("name"); 
if (file.is_open()) { 
    files.push_back(file); 
} 

// close files 
for (list<ifstream>::iterator i = files.begin(); iter++; i != files.end()) { 
    i->close(); 
} 
0

449:

Après avoir supprimé le tableau, vous allez rond et commencer à essayer d'ouvrir des fichiers à nouveau - le cas échéant des appels ouverts vous ne serez frappé dans la boucle pour toujours. Vous devez utiliser un return ou un break après avoir supprimé le tableau.

1

Je Structurer le code plus comme ceci:

for all input names 
    if (!open file) 
     break; 

if (number of open files != number of input names) 
    close the files that did open 
return (possibly empty) list of files 
Questions connexes