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.
Ich würde eine Skriptsprache verwenden – P0W
@ P0W: Eine höhere Abstraktionssprache wie Python, ja, aber keine Skriptsprache. – Olaf
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. –