[C] Eliminare commenti da un file sorgente in C
-
- Imperturbabile Insigne
- Messaggi: 2739
- Iscrizione: mercoledì 16 gennaio 2013, 17:28
- Desktop: ubuntu-2d
- Distribuzione: Ubuntu 12.04.2 LTS i686
- Località: Airuno(Lecco)
Re: [C] Eliminare commenti da un file sorgente in C
Secondo me è un problema molto complesso in fase di studio base del c
Non so se vale la pena.mi sembrano cose che dovrebbero venire dopo
Non so se vale la pena.mi sembrano cose che dovrebbero venire dopo
Re: [C] Eliminare commenti da un file sorgente in C
Intendo righe di programma, se apro gli apici e vado a caporiga, quello che scrivo e' inteso come fuori dalla stringa.Se provi a spostarlo in un editor "a colori", per esempio quello di Code::Blocks, si vede che la stringa continua per tutta la prima riga ma la seconda è commento, la "definizione" non può durare più di una riga.
Codice: Seleziona tutto
char s[] = "All'interno della stringa
// è un commento, nonostante non ci sia stato un " di chiusura
- vbextreme
- Entusiasta Emergente
- Messaggi: 1214
- Iscrizione: domenica 12 gennaio 2014, 14:06
- Desktop: lxde
- Distribuzione: xubuntu 14.10
Re: [C] Eliminare commenti da un file sorgente in C
io farei un automa come in allegato.
che trasformato in codice salta fuori una cosa tipo questa:
gli va passato il file di origine e quello di destinazione.
se compilate con "-D_DEBUG" potete vedere come funzionano i vari passaggi.
[edit]
nella linea che va da B a S manca il testo, non l'ha salvata quando ho esportato come jpg , il testo è
StartCpy()
'\n'
[/edit]
che trasformato in codice salta fuori una cosa tipo questa:
Codice: Seleziona tutto
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio_ext.h>
#include <time.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>
#include <errno.h>
#include <stdbool.h>
#if _DEBUG
void waitenter()
{
printf("wait enter");
char c[80];
fgets(c,80,stdin);
}
#endif
#define MAXSTACK 1024
static char stk[MAXSTACK];
static int istk = 0;
int push(char c)
{
if ( istk >= MAXSTACK ) return -1;
stk[istk++] = c;
return 0;
}
int pop(void)
{
if ( istk <= 0 ) return -1;
return stk[--istk];
}
/**********************************************************************/
typedef struct _RWFILE
{
FILE* r;
FILE* w;
}RWFILE;
int rwopen(RWFILE* f, char* source, char* dest)
{
f->r = fopen(source,"r");
if ( NULL == f->r ) return -1;
f->w = fopen(dest,"w");
if ( NULL == f->w ) { fclose(f->r); return -2;}
return 0;
}
#define rwgetc(F) ({ int c = fgetc(F->r); c; })
#define rwputc(C,F) ({ if ( C != EOF ) fputc(C, F->w); })
int rwclose(RWFILE* f)
{
fclose(f->r);
fclose(f->w);
return 0;
}
/**********************************************************************/
typedef int(*state_f)(RWFILE*, int);
typedef enum { _S, _A, _B, _C, _D, _E, _F, _Z, _COUNT} state_e;
static state_e stateautomata = 0;
int automata_S(RWFILE* f, int c)
{
if ( c == '/' )
{
stateautomata = _A;
}
else if ( c == '\"' )
{
push(c);
rwputc(c, f);
stateautomata = _F;
}
else if ( c == EOF )
{
stateautomata = _E;
}
else
{
rwputc(c, f);
}
return 0;
}
int automata_A(RWFILE* f, int c)
{
if ( c == '/' )
{
stateautomata = _B;
}
else if ( c == '*' )
{
push(c);
stateautomata = _C;
}
else if ( c == EOF )
{
stateautomata = _E;
}
else
{
rwputc('/', f);
rwputc(c, f);
stateautomata = _S;
}
return 0;
}
int automata_B(RWFILE* f, int c)
{
if ( c == '\n' )
{
rwputc(c, f);
stateautomata = _S;
}
else if ( c == EOF )
{
stateautomata = _E;
}
return 0;
}
int automata_C(RWFILE* f, int c)
{
if ( c == '*' )
{
stateautomata = _D;
}
else if ( c == EOF )
{
stateautomata = _Z;
}
return 0;
}
int automata_D(RWFILE* f, int c)
{
if ( c == '/' )
{
if ( pop() != '*' ) return -1;
stateautomata = _S;
}
else if ( c == EOF )
{
stateautomata = _Z;
}
else
{
stateautomata = _C;
}
return 0;
}
int automata_E(RWFILE* f, int c)
{
return 1;
}
int automata_F(RWFILE* f, int c)
{
if ( c == '"' )
{
if ( pop() != '"' ) return -1;
stateautomata = _S;
}
else if ( c == EOF )
{
stateautomata = _Z;
}
rwputc(c, f);
return 0;
}
int automata_Z(RWFILE* f, int c)
{
return -1;
}
static state_f fncautomata[_COUNT] = { automata_S, automata_A, automata_B, automata_C, automata_D,
automata_E, automata_F, automata_Z };
int automata_state(RWFILE* f)
{
int c;
int ret;
do
{
c = rwgetc(f);
#if _DEBUG
printf("read :%c \n",c);
printf("state:%d \n",stateautomata);
#endif
ret = fncautomata[stateautomata](f, c);
#if _DEBUG
printf("ret :%d \n",ret);
waitenter();
#endif
}while( 0 == ret );
return ret;
}
int main(int argc, char** argv)
{
if ( argc != 3 )
{
fputs("source.c dest.c\n", stderr);
return -7;
}
RWFILE rw;
int ret = rwopen(&rw, argv[1], argv[2]);
if ( ret == -1 ) { fputs("error to open source file\n", stderr); return -1; }
if ( ret == -2 ) { fputs("error to open dest file\n", stderr); return -2; }
ret = automata_state(&rw);
rwclose(&rw);
if ( ret != 1 )
{
fputs("error to parse file, incorrect close comment or close double quote\n",stderr);
return -3;
}
return 0;
}
se compilate con "-D_DEBUG" potete vedere come funzionano i vari passaggi.
[edit]
nella linea che va da B a S manca il testo, non l'ha salvata quando ho esportato come jpg , il testo è
StartCpy()
'\n'
[/edit]
Re: [C] Eliminare commenti da un file sorgente in C
Ma pop e' uguale farla ritornare char, no?
- crap0101
- Rampante Reduce
- Messaggi: 8242
- Iscrizione: martedì 30 ottobre 2007, 6:33
- Desktop: LXDE
- Distribuzione: Ubuntu 18.04.1 LTS
- Sesso: Maschile
- Località: TO
- Contatti:
Re: [C] Eliminare commenti da un file sorgente in C
bè così però è proprio _sbagliato_, non è roba compilabile, io intendevo:sbam [url=http://forum.ubuntu-it.org/viewtopic.php?p=4851594#p4851594][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:Intendo righe di programma, se apro gli apici e vado a caporiga, quello che scrivo e' inteso come fuori dalla stringa.Se provi a spostarlo in un editor "a colori", per esempio quello di Code::Blocks, si vede che la stringa continua per tutta la prima riga ma la seconda è commento, la "definizione" non può durare più di una riga.Codice: Seleziona tutto
char s[] = "All'interno della stringa // è un commento, nonostante non ci sia stato un " di chiusura
Codice: Seleziona tutto
crap0101@orange:/tmp/foo$ cat x.c
#include <stdio.h>
int main (void) {
char s[] = "foo \
// è un commento, nonostante non ci sia stato un \" di chiusura \
bar \
baz \
";
puts(s);
return 0;
}
http://www.gnu.org/ http://boinc.berkeley.edu/ http://www.python-it.org/
- Ricorda le ultime parole di suo padre: «Sta' alla larga dalle chiese, figlio. La sola cosa per cui hanno la chiave è il merdaio. E giurami che non porterai mai un distintivo della legge» - W.S. Burroughs
- Ricorda le ultime parole di suo padre: «Sta' alla larga dalle chiese, figlio. La sola cosa per cui hanno la chiave è il merdaio. E giurami che non porterai mai un distintivo della legge» - W.S. Burroughs
Re: [C] Eliminare commenti da un file sorgente in C
Non e' compito del programma controllare se sia corretto o menosbam [url=http://forum.ubuntu-it.org/viewtopic.php?p=4851569#p4851569][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:che poi in C/C++ sia scorretto e' un'altra cosa.
Re: [C] Eliminare commenti da un file sorgente in C
Premetto che non e' il genere di esercizio che mi esalta, ma io semplificherei di brutto lavorando su un'unico buffer anziche' complicarmi la vita con blocchi o singole letture.
Per cui il _mio_ approccio "semplicistico" consiste nel preallocare un blocco sufficientemente grande per l'intero file, magari una sola lettura, per poi gestirmi gli stati e stampare tutto quello che non rientra nel REM su stdout.
Sinceramente non so se ho sbagliato qualcosa, magari nella zona "QUOTE", ma mi sono limitato a testatare i tempi su file decisamente grandicelli:
codice:
Per cui il _mio_ approccio "semplicistico" consiste nel preallocare un blocco sufficientemente grande per l'intero file, magari una sola lettura, per poi gestirmi gli stati e stampare tutto quello che non rientra nel REM su stdout.
Sinceramente non so se ho sbagliato qualcosa, magari nella zona "QUOTE", ma mi sono limitato a testatare i tempi su file decisamente grandicelli:
Codice: Seleziona tutto
max@studio:/tmp$ gcc -Wall -pedantic -O2 del.c -o del
max@studio:/tmp$ time ./del < /usr/include/GL/glew.h > glew.h
real 0m0.020s
user 0m0.012s
sys 0m0.004s
max@studio:/tmp$ time ./del < /usr/include/GL/glew.h > glew.h
max@studio:/tmp$
real 0m0.020s
user 0m0.012s
sys 0m0.004s
max@studio:/tmp$ wc /usr/include/GL/glew.h glew.h
16126 61686 837247 /usr/include/GL/glew.h
16038 57311 785065 glew.h
32164 118997 1622312 totale
max@studio:/tmp$
max@studio:/tmp$ gcc -c glew.h
max@studio:/tmp$
Codice: Seleziona tutto
#include <stdio.h>
#define MAX_BUF 8000000 /* 8M */
#define ESCAPED (p>buf?*(p-1)=='\\'||*(p-1)=='\'':0)
char buf[MAX_BUF],*p,state;
enum {CODE,QUOTE,REM};
void skip_rem()
{
p=buf;
while(*p)
{
if (state==CODE&&*p=='/')
{
if (*(p+1)=='*') state=REM,p+=2; /* REM C89 */
else if (*(p+1)=='/') while(*++p&&*p!='\n'); /* REM C99 */
}
else if (state==REM&&*p=='*'&&*(p+1)=='/')
state=CODE,p+=2; /* BYE-BYE REM */
else if (state!=REM&&*p=='"'&&!ESCAPED)
state=!state; /* CODE<-->QUOTE */
if (state!=REM) /* CODE or QUOTE */
putchar(*p);
p++;
}
}
int main(int argc, char **argv)
{
if ((fread(buf, 1, MAX_BUF, stdin))==MAX_BUF)
return fputs("fatal:buffer overflow!\n",stderr);
skip_rem();
if (state==QUOTE) fputs("warning:unmatched quote!\n",stderr);
else if (state==REM) fputs("warning:unmatched rem!\n",stderr);
return (int)state;
}
-
- Scoppiettante Seguace
- Messaggi: 289
- Iscrizione: mercoledì 11 giugno 2014, 14:12
- Desktop: Lubuntu
- Distribuzione: Ubuntu 20.04.3 LTS
Re: [C] Eliminare commenti da un file sorgente in C
@ixamit non uso spesso stdin associato a fread, ma se funziona come per i file normali (e dovrebbe essere così) allora il tuo buffer non non ha garanzie di avere un 0 finale.
Comunque sono d'accordo anche io per evitare tutte quelle scritture e/o letture piccole che fanno perdere tempo inutile in accessi al disco...
EDIT: scusate ho editato il codicello un paio di volte
Comunque sono d'accordo anche io per evitare tutte quelle scritture e/o letture piccole che fanno perdere tempo inutile in accessi al disco...
Codice: Seleziona tutto
(...)
FILE *f = fopen("il_tuo_file.c", "rb");
fseek(f, 0, SEEK_END);
long file_size = ftell(f);
fseek(f, 0, SEEK_SET);
if( file_size >= MASSIMA_LUNGHEZZA_FILE_PERMESSA ) {
fclose(f);
return;
}
fread(buffer, file_size, 1, f);
fclose(f);
buffer[file_size] = 0;
ecc...
Ultima modifica di fabio massacci il mercoledì 10 febbraio 2016, 18:49, modificato 3 volte in totale.
Re: [C] Eliminare commenti da un file sorgente in C
Ma secondo me si fa prima a non usare un buffer, questa è la mia soluzione senza buffer usando solo due variabili char alla fine
Non sarà bellissima ne leggibilissima, ma funziona bene ed è stata relativamente veloce da scrivere (una decina di minuti) e funziona bene (provato su più file header in /usr/include e poi compilano bene), è anche veloce alla fine, probabilmente si può anche ottimizzare di più in certi punti anche, non ha limitazioni su quanto deve essere grosso il buffer e non consuma praticamente memoria dato che le uniche variabili che usa sono due char, e probabilmente è anche veloce dato che non deve gestire buffer e tutto
Codice: Seleziona tutto
#include <stdio.h>
int main(){
char ch, nextch;
while ((ch=getchar())!=EOF) {
if (ch=='/'){
nextch = getchar();
if (nextch=='/') {
while (getchar()!='\n');
} else if (nextch=='*') {
ch = getchar();
while (1) {
if (ch=='*') {
ch = getchar();
if (ch=='/') break;
} else {
ch = getchar();
}
}
} else {
putchar(ch);
putchar(nextch);
}
} else if (ch=='"') {
putchar(ch);
while ((ch=getchar())){
putchar(ch);
if (ch=='\\') putchar(getchar());
if (ch=='"') break;
}
} else if (ch=='\'') {
putchar(ch);
while ((ch=getchar())){
putchar(ch);
if (ch=='\\') putchar(getchar());
if (ch=='\'') break;
}
} else {
putchar(ch);
}
}
return 0;
}
-
- Scoppiettante Seguace
- Messaggi: 289
- Iscrizione: mercoledì 11 giugno 2014, 14:12
- Desktop: Lubuntu
- Distribuzione: Ubuntu 20.04.3 LTS
Re: [C] Eliminare commenti da un file sorgente in C
@ale4 guarda, non è che si voglia per forza leggere un file tutto insieme (ne tanto meno volevo per forza porre limiti al file), era per dare un'alternativa a quelli che ne vogliono leggere/scrivere pochi byte per volta, peggio ancora se parliamo di un byte per volta. Tu e ixamit usate i pipe quindi forse demandate al sistema operativo l'onere di decidere quanti byte per volta estrarre/scrivere dai file coinvolti, cosa che potrebbe fare in maniera più efficiente di noi, però magari anche lì se ad ogni putchar e ad ogni getchar corrisponde una richiesta diversa di accesso al disco(non è detto), be capisci da solo che è meno efficiente, preferisco allora leggere/scrivere il file un tot per volta ma dove quel tot sia almeno di diversi KB.
intendiamoci forse con il compito di questo post non vale la pena ottimizzare troppo ma fare le cose più velocemente non ha mai fatto troppo male
intendiamoci forse con il compito di questo post non vale la pena ottimizzare troppo ma fare le cose più velocemente non ha mai fatto troppo male
- vbextreme
- Entusiasta Emergente
- Messaggi: 1214
- Iscrizione: domenica 12 gennaio 2014, 14:06
- Desktop: lxde
- Distribuzione: xubuntu 14.10
Re: [C] Eliminare commenti da un file sorgente in C
putchar e getchar sono bufferizzate.
In passato abbiamo già provato e il buffer di sistema è più veloce che la lettura totale del file in un colpo solo.
In passato abbiamo già provato e il buffer di sistema è più veloce che la lettura totale del file in un colpo solo.
Re: [C] Eliminare commenti da un file sorgente in C
Le pipe copiano i dati in blocco, nel caso di linux 4096byte o 4k, ossia una pagina di memoria alla fine, inoltre poi il kernel applica varie ottimizzazioni, quando apri un file anche con la chiamata di sistema open il kernel precaria in ram un tot di blocchi del file (non so quanti anche perché dipende dal kernel), perché prevede le letture successive per esempio, o usa altri algoritmi intelligenti per limitare le scritture su disco, previa ovviamente ram non utilizzata (ovviamente la memoria allocata dai programmi ha la priorità su quella allocata dalla cache dei file), insomma il kernel, linux in particolare, sotto questo aspetto è molto ottimizzato, e anche la libreria C lo è, infatti se il programma viene lanciato con output su una pipe non svuota il buffer ad ogni newline ma piuttosto lo svuota raggiunta la dimensione della pagina, ossia dopo 4096 byte
Puoi controllare comunque questo comportamento lanciando il programma con strace alla fine, vedi che le chiamate read e write sono esattamente da 4096 byte
Puoi controllare comunque questo comportamento lanciando il programma con strace alla fine, vedi che le chiamate read e write sono esattamente da 4096 byte
-
- Scoppiettante Seguace
- Messaggi: 289
- Iscrizione: mercoledì 11 giugno 2014, 14:12
- Desktop: Lubuntu
- Distribuzione: Ubuntu 20.04.3 LTS
Re: [C] Eliminare commenti da un file sorgente in C
si infatti questo lo immaginavo, comunque anche usando una pipe, preferisco usare una fread per riempire un buffer da, che so, 4096 byte e poi scorrerlo con un puntatore piuttosto che fare 4096 chiamate a getchar
Re: [C] Eliminare commenti da un file sorgente in C
I dati allocati su .bss sono storicamente inizializzati a zero.fabio masacci ha scritto: @ixamit non uso spesso stdin associato a fread, ma se funziona come per i file normali (e dovrebbe essere così) allora il tuo buffer non non ha garanzie di avere un 0 finale.
-
- Scoppiettante Seguace
- Messaggi: 289
- Iscrizione: mercoledì 11 giugno 2014, 14:12
- Desktop: Lubuntu
- Distribuzione: Ubuntu 20.04.3 LTS
Re: [C] Eliminare commenti da un file sorgente in C
si giusto mea culpaixamit [url=http://forum.ubuntu-it.org/viewtopic.php?p=4851818#p4851818][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:I dati allocati su .bss sono storicamente inizializzati a zero.fabio masacci ha scritto: @ixamit non uso spesso stdin associato a fread, ma se funziona come per i file normali (e dovrebbe essere così) allora il tuo buffer non non ha garanzie di avere un 0 finale.
- Vincenzo1968
- Scoppiettante Seguace
- Messaggi: 450
- Iscrizione: lunedì 14 gennaio 2013, 14:21
- Desktop: Unity
- Distribuzione: Ubuntu 18.04.3 LTS x86_64
- Località: Villabate(PA)
- Contatti:
Re: [C] Eliminare commenti da un file sorgente in C
La mia soluzione:
L'automa è implementato tramite switch come spiegato da Claudio_F qui.
Codice: Seleziona tutto
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BLOCK_SIZE 4096
typedef enum tagStates
{
S0,
S1,
S2,
S3,
S4,
S5,
S6,
S7,
S8
} States;
int makeOutput(const char *szFileName, const char *szNewFileName);
int makeOutput(const char *szFileName, const char *szNewFileName)
{
int retValue = 1;
FILE *fp = NULL;
FILE *fpNew = NULL;
unsigned char *myBlock = NULL;
unsigned char *myBlockNew = NULL;
int blockLen = 0;
int index1 = 0;
int index2 = 0;
States state = S0;
char c;
myBlock = (unsigned char *)malloc(sizeof(unsigned char) * BLOCK_SIZE);
if ( !myBlock )
{
printf("Memoria insufficiente.\n");
retValue = 0;
goto uscita;
}
myBlockNew = (unsigned char *)malloc(sizeof(unsigned char) * BLOCK_SIZE);
if ( !myBlockNew )
{
printf("Memoria insufficiente.\n");
retValue = 0;
goto uscita;
}
fp = fopen(szFileName, "rb");
if ( fp == NULL )
{
printf("Errore nell'apertura del file '%s'.\n", szFileName);
retValue = 0;
goto uscita;
}
fpNew = fopen(szNewFileName, "wb");
if ( fpNew == NULL )
{
printf("Errore nella creazione del file '%s'.\n", szNewFileName);
retValue = 0;
goto uscita;
}
while ( (blockLen = fread(myBlock, 1, BLOCK_SIZE, fp)) )
{
index1 = 0;
while ( index1 < blockLen )
{
c = myBlock[index1++];
switch ( state )
{
case S0:
if ( c == '/' )
{
state = S1;
}
else if ( c == '"' )
{
myBlockNew[index2++] = c;
state = S2;
}
else if ( c == '\'' )
{
myBlockNew[index2++] = c;
state = S7;
}
else
{
myBlockNew[index2++] = c;
}
break;
case S1:
if ( c == '*' )
{
state = S3;
}
else if ( c == '/' )
{
state = S4;
}
else
{
myBlockNew[index2++] = c;
}
break;
case S2:
myBlockNew[index2++] = c;
if ( c == '"' )
{
state = S0;
}
else if ( c == '\\' )
{
state = S5;
}
break;
case S3:
if ( c == '*' )
{
state = S6;
}
break;
case S4:
if ( c == '\r' || c == '\n' )
{
myBlockNew[index2++] = c;
state = S0;
}
break;
case S5:
myBlockNew[index2++] = c;
state = S2;
break;
case S6:
if ( c == '/' )
{
state = S0;
}
else
{
state = S3;
}
break;
case S7:
myBlockNew[index2++] = c;
if ( c >= '\\' )
{
state = S8;
}
else if ( c == '\'' )
{
state = S0;
}
break;
case S8:
myBlockNew[index2++] = c;
state = S7;
break;
} /* Fine switch */
if ( index2 >= BLOCK_SIZE )
{
fwrite(myBlockNew, 1, BLOCK_SIZE, fpNew);
index2 = 0;
}
}
}
if ( index2 > 0 )
fwrite(myBlockNew, index2, 1, fpNew);
uscita:
if ( myBlock)
free(myBlock);
if (myBlockNew )
free(myBlockNew);
if ( fp )
fclose(fp);
if ( fpNew )
fclose(fpNew);
return retValue;
}
/*
gcc -Wall -Wextra -pedantic -O2 togli_commenti.c -o togli_commenti
*/
int main(int argc, char **argv)
{
if(argc != 3)
{
printf("uso: %s fileInput fileOutput\n", argv[0]);
return -1;
}
makeOutput(argv[1], argv[2]);
return 0;
}
È ormai difficile incontrare un cretino che non sia intelligente e un intelligente che non sia un cretino. [...] Oh i bei cretini di una volta! Genuini, integrali. Come il pane di casa. Come l'olio e il vino dei contadini. (da "Nero su nero" di Leonardo Sciascia)
Re: [C] Eliminare commenti da un file sorgente in C
ciao Vincenzo1968!
E' buggata, ma del resto come la mia e quella di ale4.
Sotto trovi gli estremi:
E' buggata, ma del resto come la mia e quella di ale4.
Sotto trovi gli estremi:
Codice: Seleziona tutto
#include <xxx/yyy.h>
void foo()
{
int a=4/2;
}
- Vincenzo1968
- Scoppiettante Seguace
- Messaggi: 450
- Iscrizione: lunedì 14 gennaio 2013, 14:21
- Desktop: Unity
- Distribuzione: Ubuntu 18.04.3 LTS x86_64
- Località: Villabate(PA)
- Contatti:
Re: [C] Eliminare commenti da un file sorgente in C
Ciao ixamit,ixamit [url=http://forum.ubuntu-it.org/viewtopic.php?p=4853001#p4853001][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:ciao Vincenzo1968!
E' buggata, ma del resto come la mia e quella di ale4.
Sotto trovi gli estremi:Codice: Seleziona tutto
#include <xxx/yyy.h> void foo() { int a=4/2; }
grazie per la segnalazione.
Così dovrebbe andare:
Codice: Seleziona tutto
#define _FILE_OFFSET_BITS 64
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BLOCK_SIZE 4096
typedef enum tagStates
{
S0,
S1,
S2,
S3,
S4,
S5,
S6,
S7,
S8
} States;
int makeOutput(const char *szFileName, const char *szNewFileName);
int makeOutput(const char *szFileName, const char *szNewFileName)
{
int retValue = 1;
FILE *fp = NULL;
FILE *fpNew = NULL;
unsigned char *myBlock = NULL;
unsigned char *myBlockNew = NULL;
int blockLen = 0;
int index1 = 0;
int index2 = 0;
States state = S0;
char c;
myBlock = (unsigned char *)malloc(sizeof(unsigned char) * BLOCK_SIZE);
if ( !myBlock )
{
printf("Memoria insufficiente.\n");
retValue = 0;
goto uscita;
}
myBlockNew = (unsigned char *)malloc(sizeof(unsigned char) * BLOCK_SIZE);
if ( !myBlockNew )
{
printf("Memoria insufficiente.\n");
retValue = 0;
goto uscita;
}
fp = fopen(szFileName, "rb");
if ( fp == NULL )
{
printf("Errore nell'apertura del file '%s'.\n", szFileName);
retValue = 0;
goto uscita;
}
fpNew = fopen(szNewFileName, "wb");
if ( fpNew == NULL )
{
printf("Errore nella creazione del file '%s'.\n", szNewFileName);
retValue = 0;
goto uscita;
}
while ( (blockLen = fread(myBlock, 1, BLOCK_SIZE, fp)) )
{
index1 = 0;
while ( index1 < blockLen )
{
c = myBlock[index1++];
switch ( state )
{
case S0:
if ( c == '/' )
{
state = S1;
}
else if ( c == '"' )
{
myBlockNew[index2++] = c;
state = S2;
}
else if ( c == '\'' )
{
myBlockNew[index2++] = c;
state = S7;
}
else
{
myBlockNew[index2++] = c;
}
break;
case S1:
if ( c == '*' )
{
state = S3;
}
else if ( c == '/' )
{
state = S4;
}
else
{
myBlockNew[index2++] = '/';
if ( index2 >= BLOCK_SIZE )
{
fwrite(myBlockNew, 1, BLOCK_SIZE, fpNew);
index2 = 0;
}
myBlockNew[index2++] = c;
state = S0;
}
break;
case S2:
myBlockNew[index2++] = c;
if ( c == '"' )
{
state = S0;
}
else if ( c == '\\' )
{
state = S5;
}
break;
case S3:
if ( c == '*' )
{
state = S6;
}
break;
case S4:
if ( c == '\r' || c == '\n' )
{
myBlockNew[index2++] = c;
state = S0;
}
break;
case S5:
myBlockNew[index2++] = c;
state = S2;
break;
case S6:
if ( c == '/' )
{
state = S0;
}
else
{
state = S3;
}
break;
case S7:
myBlockNew[index2++] = c;
if ( c >= '\\' )
{
state = S8;
}
else if ( c == '\'' )
{
state = S0;
}
break;
case S8:
myBlockNew[index2++] = c;
state = S7;
break;
} /* Fine switch */
if ( index2 >= BLOCK_SIZE )
{
fwrite(myBlockNew, 1, BLOCK_SIZE, fpNew);
index2 = 0;
}
}
}
if ( index2 > 0 )
fwrite(myBlockNew, index2, 1, fpNew);
uscita:
if ( myBlock)
free(myBlock);
if (myBlockNew )
free(myBlockNew);
if ( fp )
fclose(fp);
if ( fpNew )
fclose(fpNew);
return retValue;
}
/*
gcc -Wall -Wextra -pedantic -O2 togli_commenti.c -o togli_commenti
*/
int main(int argc, char **argv)
{
if(argc != 3)
{
printf("uso: %s fileInput fileOutput\n", argv[0]);
return -1;
}
makeOutput(argv[1], argv[2]);
return 0;
}
È ormai difficile incontrare un cretino che non sia intelligente e un intelligente che non sia un cretino. [...] Oh i bei cretini di una volta! Genuini, integrali. Come il pane di casa. Come l'olio e il vino dei contadini. (da "Nero su nero" di Leonardo Sciascia)
- Claudio_F
- Entusiasta Emergente
- Messaggi: 1463
- Iscrizione: lunedì 28 maggio 2012, 18:49
- Desktop: Mate/Gnome
- Distribuzione: Ubu22.04
Re: [C] Eliminare commenti da un file sorgente in C
@Vincenzo mi sa che ho letto la prima versione, gli stati sono praticamente gli stessi a cui avevo pensato io ma c'è qualche errore di logica come il mancato ritorno allo stato 0 dopo aver rilevato il primo /.
Comunque mi sembra inutile fare un enum S0 S1 S2 ecc per indicare 0 1 2 ecc Mi sembra più utile/comprensibile qualcosa del genere:L'automa corretto di quelle poche cose che ho visto dovrebbe essere questo:
EDIT: aggiunto possibilità di \ finale in stringhe e commenti per continuazione su riga successiva
Comunque mi sembra inutile fare un enum S0 S1 S2 ecc per indicare 0 1 2 ecc Mi sembra più utile/comprensibile qualcosa del genere:
Codice: Seleziona tutto
typedef enum tagStates
{
Normal, // codice normale
InStr, // all'interno di una stringa
InChr, // all'interno di un carattere
EscStr, // sequenza escape in stringa
EscChr, // sequenza escape in carattere
Sdetect, // rilevato possibile / inizio commento
Mdetect, // rilevato possibile * di fine commento
BsDetect, // rilevato \ finale in commento //
ComSS, // all'interno di commento //
ComSM, // all' interno di commento /* */
Error // errore fine riga in stringa o carattere
} States;
Codice: Seleziona tutto
switch ( state ){
case Normal:
if ( c == '/' ) state = Sdetect;
else if ( c == '"' ) {myBlockNew[index2++] = c; state = InStr;}
else if ( c == '\'' ) {myBlockNew[index2++] = c; state = InChr;}
else myBlockNew[index2++] = c;
break;
case InStr:
myBlockNew[index2++] = c;
if ( c == '\r' || c == '\n' ) state = Error;
else if ( c == '"' ) state = Normal;
else if ( c == '\\' ) state = EscStr;
break;
case EscStr:
myBlockNew[index2++] = c;
state = InStr;
break;
case InChr:
myBlockNew[index2++] = c;
if ( c == '\r' || c == '\n' ) state = Error;
else if ( c == '\'' ) state = Normal;
else if ( c == '\\' ) state = EscChr;
break;
case EscChr:
myBlockNew[index2++] = c;
if ( c == '\r' || c == '\n' ) state = Error;
else state = InChr;
break;
case Sdetect:
if ( c == '*' ) state = ComSM;
else if ( c == '/' ) state = ComSS;
else {myBlockNew[index2++] = '/';
myBlockNew[index2++] = c;
state = Normal;}
break;
case ComSS:
if ( c == '\r' || c == '\n' ) {myBlockNew[index2++] = c;
state = Normal;}
else if ( c == '\\' ) state = BsDetect;
break;
case BsDetect:
myBlockNew[index2++] = c;
state = ComSS;
break;
case ComSM:
if ( c == '*' ) state = Mdetect;
break;
case Mdetect:
if ( c == '/' ) state = Normal;
else state = ComSM;
break;
case Error;
break;
} /* Fine switch */
EDIT: aggiunto possibilità di \ finale in stringhe e commenti per continuazione su riga successiva
Ultima modifica di Claudio_F il mercoledì 17 febbraio 2016, 18:10, modificato 2 volte in totale.
- Vincenzo1968
- Scoppiettante Seguace
- Messaggi: 450
- Iscrizione: lunedì 14 gennaio 2013, 14:21
- Desktop: Unity
- Distribuzione: Ubuntu 18.04.3 LTS x86_64
- Località: Villabate(PA)
- Contatti:
Re: [C] Eliminare commenti da un file sorgente in C
Si infatti. È per questo che l'output col sorgente postato da ixamit risulta errato(si mangia il "/": p. es. "4/2" nel sorgente, diventa "42" nel file di output). Ho corretto nella seconda versione.Claudio_F [url=http://forum.ubuntu-it.org/viewtopic.php?p=4853037#p4853037][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:@Vincenzo mi sa che ho letto la prima versione, gli stati sono praticamente gli stessi a cui avevo pensato io ma c'è qualche errore di logica come il mancato ritorno allo stato 0 dopo aver rilevato il primo /.
Giustissimo. Usare nomi esplicativi rende il codice più leggibile. Mea culpa.Comunque mi sembra inutile fare un enum S0 S1 S2 ecc per indicare 0 1 2 ecc Mi sembra più utile/comprensibile qualcosa del genere:
È ormai difficile incontrare un cretino che non sia intelligente e un intelligente che non sia un cretino. [...] Oh i bei cretini di una volta! Genuini, integrali. Come il pane di casa. Come l'olio e il vino dei contadini. (da "Nero su nero" di Leonardo Sciascia)
Chi c’è in linea
Visualizzano questa sezione: 0 utenti iscritti e 21 ospiti