2016-07-18 32 views
0

Ich weiß, diese Art von Frage wurde zuvor beantwortet, aber ich habe meine eigene Lösung und ich möchte den Fehler darin lösen. Ich mache mir keine Sorgen in Zitat-Kommentaren, ich weiß, dass dieser Code nicht mit ihnen umgehen wird. Das Problem ist, dass der anfängliche / Start von /* … */ Kommentar in die Datei gedruckt wird, wenn es nicht sein sollte.Entfernen von c Kommentare aus einer Datei

int cleanFile(char *fileName){ 

FILE *fp; 
fp = fopen(fileName, "r"); 
int inComment = 0; 
char current, next; 

//will return exit exicution if the file does not exist 
if(fp == NULL){ 
    printf("%s", "File was not found.\nFile is expected to be in src directory."); 
    return 0; 
} 
//creat a new file for the clean input 
FILE *cf; 
cf = fopen("cleaninput.txt", "w"); 

current = fgetc(fp); 

while(current != EOF){ 

    if(inComment == 0){ 

     if(current == '/') 
     { 
      next = fgetc(fp); 

       //look ahead and see if this is the start of a comment 
       if(next == '*') 
       { 

        inComment = 1; 
        current = next; //CODE JUMPS FROM HERE 

       }else{ 

        fputc(current, cf); 
        current = next; 

       } 
     }else{ 
      fputc(current, cf); 
      current = fgetc(fp); // AND LANDS HERE 
     } 

    //if an exit sequence is found set in comment to false 
    }else{ 
     if(current == '*') 
     { 
      next = fgetc(fp); 
      if(next == '/') 
      { 
       inComment = 0; 
       current = next; 
      } 
     }else{ 
      current = fgetc(fp); 
     } 
    } 
}//end while 

fclose(fp); 
fclose(cf); 

return 1; 
} 
+0

Ich würde eine Skriptsprache verwenden – P0W

+0

@ P0W: Eine höhere Abstraktionssprache wie Python, ja, aber keine Skriptsprache. – Olaf

+0

Beachten Sie, dass 'fgetc()' ein 'int' zurückgibt, kein' char'. Daher muss 'current' ein' int' sein. Andernfalls kann EOF nicht zuverlässig erkannt werden. Wenn Sie jedoch einen einfachen Char-Typ signiert haben, kommen Sie normalerweise damit durch. –

Antwort

0

Unter der Annahme, dass der Kommentar nicht mehr Zeilen nicht überspannt, wäre es nicht einfacher, wenn Sie die gesamte Zeile zu ignorieren, wenn das erste Zeichen mit dem Schrägstrich beginnt?

Ich denke, das Problem könnte in Ihrer zweiten IF-Anweisung sein, überprüfen Sie Ihren bedingten Ausdruck. Wenn das gelesene Zeichen kein Sternchen ist, schreibt Ihr Programm sofort in die Datei.

Wenn Sie die folgende Zeile in Ihrem Quellcode haben.

// Something here 

Ihr Programm liest das erste Zeichen, in diesem Fall des Schrägstrich, dann ist es das zweite Zeichen liest, die auch der Schrägstrich ist, nicht ein Sternchen. Daher wird die ELSE-Anweisung ausgeführt, sodass Ihr Programm in die Ausgabedatei schreibt und nicht die gesamte Zeile ignoriert.

+0

Kommentare erstrecken sich über mehrere Zeilen. Kommentare können mehrfach in einer Zeile vorkommen: 'extern int somefunc (int/* arg1 * /, char */* arg2 * /);' zum Beispiel. Wenn Sie mit dem Umgang mit Kommentaren nichts anfangen können, wird der Code anderer Leute Sie beißen.Die Leute machen die merkwürdigsten und irritierendsten Dinge in ihrem Code - und ein Kommentar-Stripper kann es sich nicht leisten, falsch zu liegen. –

1

Ihr Problem ist nicht, dass die führende / gedruckt wird, sondern dass die nachfolgende / gedruckt wird. Sie können dies beheben, indem Sie current auf das nächste Eingabezeichen setzen statt auf next, wenn next/ ist.

Mit einigen anderen (minimal) Korrekturen:

#include <stdio.h> 

static int cleanFile(char *fileName) 
{ 
    FILE *fp; 
    fp = fopen(fileName, "r"); 
    int inComment = 0; 
    int current, next; 

    /* will return exit execution if the file does not exist */ 
    if (fp == NULL) 
    { 
     printf("%s", "File was not found.\nFile is expected to be in src directory."); 
     return 0; 
    } 
    /* create a new file for the clean input */ 
    FILE *cf = fopen("cleaninput.txt", "w"); 

    current = fgetc(fp); 

    while (current != EOF) 
    { 
     if (inComment == 0) 
     { 
      if (current == '/') 
      { 
       next = fgetc(fp); 
       if (next == EOF) 
       { 
        fputc(current, cf); 
        break; 
       } 

       /* look ahead and see if this is the start of a comment */ 
       if (next == '*') 
       { 
        inComment = 1; 
        current = fgetc(fp); 
       } 
       else 
       { 
        fputc(current, cf); 
        current = next; 
       } 
      } 
      else 
      { 
       fputc(current, cf); 
       current = fgetc(fp); 
      } 
     } 
     else if (current == '*') 
     { 
      next = fgetc(fp); 
      if (next == '/') 
      { 
       inComment = 0; 
       current = fgetc(fp); 
      } 
      else 
      { 
       current = next; 
      } 
     } 
     else 
     { 
      current = fgetc(fp); 
     } 
    }/* end while */ 

    fclose(fp); 
    fclose(cf); 

    return 1; 
} 

int main(int argc, char **argv) 
{ 
    char *filename = "cc23.c"; 
    if (argc == 2) 
     filename = argv[1]; 
    if (cleanFile(filename)) 
     printf("OK\n"); 
    else 
     printf("Oops!\n"); 
    return 0; 
} 

Ein kleines Problem ist, dass dies keinen Kommentar mit einem leeren ersetzt, was die Bedeutung verändern könnte (oder Gültigkeit) eines Programms.

würde ich eine Funktion verwenden, um das nächste Zeichen zu spähen, ob es meine eigenen Code waren:

int fpeekc(FILE *fp) 
{ 
    int c = getc(fp); 
    if (c != EOF) 
     ungetc(c, fp); 
    return c; 
} 

Es würde die Vorausschaulogik vereinfachen. Ich würde auch die Funktion so umgestalten, dass sie an einem bereits geöffneten Dateistream arbeitet und in einen bestimmten Dateistream schreibt - das macht den Code allgemeiner.

#include <assert.h> 
#include <stdio.h> 

/* 
* This is adequate for routine comments. 
* It wouldn't spot /\ 
* * as the start of a comment, or *\ 
*/as the end of a comment (where the " * " line prefix should be ignored). 
*/ 

static int fpeekc(FILE *fp) 
{ 
    int c = getc(fp); 
    if (c != EOF) 
     ungetc(c, fp); 
    return c; 
} 

static void cleanFile(FILE *fin, FILE *fout) 
{ 
    int inComment = 0; 
    int current, next; 

    while ((current = getc(fin)) != EOF) 
    { 
     if (inComment == 0) 
     { 
      if (current == '/' && fpeekc(fin) == '*') 
      { 
       next = getc(fin); 
       assert(next == '*'); 
       inComment = 1; 
      } 
      else 
       putc(current, fout); 
     } 
     else if (current == '*' && fpeekc(fin) == '/') 
     { 
      inComment = 0; 
      next = fgetc(fin); 
      assert(next == '/'); 
     } 
     /* else do not echo comment characters */ 
    } 
} 

int main(int argc, char **argv) 
{ 
    char *filename = "cc29.c"; 
    if (argc == 2) 
     filename = argv[1]; 
    FILE *fp = fopen(filename, "r"); 
    if (fp == NULL) 
    { 
     fprintf(stderr, "Failed to open file %s for reading\n", filename); 
     return 1; 
    } 
    cleanFile(fp, stdout); 
    return 0; 
} 

Aufkantung-Newline Kombinationen erschweren Handhabung Kommentar - zum Glück, werden Sie wahrscheinlich brauchen, um über sie keine Sorge, wenn Sie einen C-Präprozessor gerade schreiben. Sie müssen sich um Zeichenketten und Mehrzeichenliterale wie '/*' kümmern - letztere sind nicht portierbar, aber trotzdem gültig und beginnen keinen Kommentar. Und C++ - Raw-Strings sind wieder eine weitere Stufe der Komplexität.