2009-10-11 5 views
0

J'ai le code suivant, jusqu'à présent, je veux vérifier si un nom de fichier est déjà dans la liste chaînée fileList (ou flist). Selon la sortie, la chaîne sauvegardée dans le premier Node a été changée quelque part dans Node* getFileName(Node *&flist) Comment est-ce arrivé? Aussi, y a-t-il quelque chose d'autre que je fais qui soit faux ou pas sûr concernant les pointeurs de Node et les cordes?Pourquoi cette chaîne est-elle modifiée?

sortie:

 
in main: file4.txt 
start of process: file4.txt 
file4.txt 
mid of process: file4.txt" 
in contains, fileName in node: file4.txt" 
in contains, target file name: file4.txt 
end of process: file4.txt" 
0 
no recursive call 

Code:

struct Node { 
    string fileName; 
    Node *link; 
}; 


/* 
* 
*/ 
bool contains (Node *&flist, string &name) { 
    Node *tempNode = *&flist; 
    while (tempNode != 0) { 
     cout << "in contains, fileName in node: " << flist->fileName << endl; 
     cout << "in contains, target file name: " << name << endl; 
     if ((tempNode->fileName) == name) { 
      return true; 
     } 
     else { 
      tempNode = tempNode->link; 
     } 
    } 
    return false; 
} 


/* 
* 
*/ 
Node* getLastNode (Node *&flist) { 
    Node *tempNode = *&flist; 
    while (tempNode != 0) { 
     tempNode = tempNode->link; 
    } 
    return tempNode; 
} 


/* 
* 
*/ 
string getFileName(string oneLine) { 
    char doubleQuote; 
    doubleQuote = oneLine[9]; 
    if (doubleQuote == '\"') { 
     string sub = oneLine.substr(10);     //getting the file name 
     string::size_type n = sub.size(); 
     sub = sub.substr(0,n-1); 
     cout << sub << endl; 
     return sub; 
    } 
    return NULL; 
} 

/* 
* 
*/ 
void process(istream &in, ostream &out, Node *&flist) { 
    cout << "start of process: " << flist->fileName << endl; 
    string oneLine;   //temp line holder 
    while (getline(in, oneLine)) { 
     //  cout << oneLine << endl; 
     string::size_type loc = oneLine.find("#include",0); 
     if (loc != string::npos) { 
      //found one line starting with "#include" 
      string name; 
      name = getFileName(oneLine); 
      cout << "mid of process: " << flist->fileName << endl; 
      bool recursive; 
      recursive = contains(flist, name); 
      cout << "end of process: " << flist->fileName << endl; 
      cout << recursive << endl; 
      if (recursive) { 
       //contains recursive include 
       cerr << "recursive include of file " << name << endl; 
       exit(-1); 
      } 
      else { 
       //valid include 
       cout << "no recursive call" << endl; 

      }//else 
     }//if 
    }//while 

}//process 
/* 
* 
*/ 
int main(int argc, char *argv[]) { 
    istream *infile = &cin;       // default value 
    ostream *outfile = &cout;       // default value 
    Node* fileList; 

    switch (argc) { 
    case 3: 
     outfile = new ofstream(argv[2]);   // open the outfile file 
     if (outfile->fail()) { 
      cerr << "Can't open output file " << argv[2] << endl; 
      exit(-1); 
     } 
     // FALL THROUGH to handle input file 
    case 2: 
     infile = new ifstream(argv[1]);   // open the input file 
     if (infile->fail()) { 
      cerr << "Can't open input file " << argv[1] << endl; 
      exit(-1); 
     } 
     else { 
      Node aFile = {argv[1], 0}; 
      fileList = &aFile; 
      cout << "in main: " << fileList->fileName << endl; 
     } 
     // FALL THROUGH 
    case 1:          // use cin and cout 
     break; 
    default:          // too many arguments 
     cerr << "Usage: " << argv[0] << " [ input-file [ output-file ] ]" << endl; 
     exit(-1);         // TERMINATE! 
    } 

    processOneFile (*infile, *outfile, fileList); 

    // do something 
    if (infile != &cin) delete infile;    // close file, do not delete cin! 
    if (outfile != &cout) delete outfile;   // close file, do not delete cout! 
} 
+0

Avez-vous essayé de passer votre code avec un débogueur? Cela devrait s'avérer plus efficace que d'utiliser les instructions 'print' pour montrer quelle instruction change vos données. –

+0

Pourriez-vous s'il vous plaît nous fournir les fichiers nécessaires pour compiler ceci? –

+0

Je vous recommande également d'utiliser std :: set pour conserver les noms de fichiers au lieu de la liste auto-construite. – dimba

Répondre

2

Pouvez-vous poster le code d'origine? Le code que vous avez publié ne compile même pas.

erreurs que j'ai remarqué, dans l'ordre:

processOneFile (*infile, *outfile, fileList); 

Il n'y a pas de procédure processOneFile().

istream *infile = &cin;       // default value 
ostream *outfile = &cout;       // default value 
Node* fileList; 
case 1:          // use cin and cout 
    break; 
processOneFile (*infile, *outfile, fileList); 

Ceci appellera processOneFile() une liste de fichiers non initialisée, qui se bloquer lorsque vous essayez d'imprimer le nom du fichier.

else { 
      Node aFile = {argv[1], 0}; 
      fileList = &aFile; 
      cout << "in main: " << fileList->fileName << endl; 
    } 

aFile est uniquement portée dans ce else, si vous essayez d'utiliser un pointeur vers elle sera plus tard l'échec.

string getFileName(string oneLine) { 
    /// 
    return NULL; 
} 

Vous ne pouvez pas construire un std::string de NULL - cela va planter le programme. Après avoir corrigé ces erreurs afin que votre code ne tombe pas en panne, je n'ai pas pu reproduire l'erreur.

Si vous construisez sous Linux, essayez d'augmenter le niveau d'avertissement (avec g++ -Wall -Wextra -ansi -pedantic) et d'exécuter votre code via valgrind, pour vérifier les erreurs de mémoire.

+0

En outre, il n'existe aucune fonction telle que "getFileName (Node * & flist)" qui provoque le problème. Il n'y a qu'un "getFileName (string oneLine)", mais il n'y a aucun moyen de changer une chaîne dans l'un des nœuds. –

+0

Vous pouvez initialiser une chaîne à partir de NULL. La chaîne sera vide. – GManNickG

+0

@GMan: Non, initialiser un 'std :: string' à partir de' NULL' n'est pas défini. Sur mon système (et le codepad, http://codepad.org/ZldIZHwo), il déclenche une exception. –

0

Ok, le code ne semble maintenant que cela fonctionne comme prévu:

#include <iostream> 
#include <fstream> 

using namespace::std; 

struct Node 
{ 
    string fileName; 
    Node *link; 
}; 

bool contains (Node *&flist, string &name) 
{ 
    Node *tempNode = *&flist; 
    while (tempNode != 0) 
    { 
     cout << "Searching in \"" << flist->fileName; 
     cout << "\" for \"" << name << "\"" << endl; 
     if (tempNode->fileName == name) 
     { 
      return true; 
     } 
     else 
     { 
      tempNode = tempNode->link; 
     } 
    } 
    return false; 
} 

Node* getLastNode (Node *&flist) 
{ 
    Node *tempNode = *&flist; 
    while (tempNode != 0) 
    { 
     tempNode = tempNode->link; 
    } 
    return tempNode; 
} 

string getFileName(string oneLine) 
{ 
    char doubleQuote; 
    doubleQuote = oneLine[9]; 
    if (doubleQuote == '\"') { 
     string sub = oneLine.substr(10);          //getting the file name 
     string::size_type n = sub.size(); 
     sub = sub.substr(0,n-1); 
     return sub; 
    } 
    return ""; 
} 

void process(istream &in, ostream &out, Node *&flist) 
{ 
    cout << "Start of process: " << flist->fileName << endl << endl; 
    string oneLine;     
    while (1) 
    { 
     cout << "Input include statement: "; 
     getline(in, oneLine); 

     if (oneLine == "STOP") 
      return; 

     string::size_type loc = oneLine.find("#include",0); 
     if (loc != string::npos) 
     { 
      //found one line starting with "#include" 
      string name; 
      name = getFileName(oneLine); 
      if (name == "") 
      { 
       cout << "Couldn't find filename, skipping line..." << endl; 
       continue; 
      } 

      if (contains(flist, name)) 
      { 
       //contains recursive include 
       cerr << "Uh, oh! Recursive include of file " << name << endl; 
       exit(-1); 
      } 
      else 
      { 
       cerr << "No recursive include" << endl; 
      } 

     }//if 

     cout << endl; 
    }//while 
} 

int main(int argc, char *argv[]) 
{ 
    Node* fileList = new Node; 
    istream *infile = &cin;       // default value 
    ostream *outfile = &cout;       // default value 
    fileList->fileName = "Input";      // default value 

    switch (argc) 
    { 
     case 3: 
      outfile = new ofstream(argv[2]);   // open the outfile file 
      if (outfile->fail()) { 
       cerr << "Can't open output file " << argv[2] << endl; 
       exit(-1); 
      } 
      // FALL THROUGH to handle input file 
     case 2: 
      infile = new ifstream(argv[1]);   // open the input file 
      if (infile->fail()) { 
       cerr << "Can't open input file " << argv[1] << endl; 
       exit(-1); 
      } 
      else { 
       fileList->fileName = argv[1]; 
       cout << "in main: " << fileList->fileName << endl; 
      } 
      // FALL THROUGH 
     case 1:          // use cin and cout 
      break; 
     default:          // too many arguments 
      cerr << "Usage: " << argv[0] << " [ input-file [ output-file ] ]" << endl; 
      exit(-1);         // TERMINATE! 
    } 

    process(*infile, *outfile, fileList); 

    // do something 
    if (infile != &cin) delete infile;    // close file, do not delete cin! 
    if (outfile != &cout) delete outfile;   // close file, do not delete cout! 
} 
0

Aussi, pourquoi perdre du temps à écrire votre propre liste chaînée lorsque la bibliothèque standard dispose déjà d'une parfaite bonne?

+0

C'est un travail à faire, bien sûr. –

Questions connexes