Antecedentes
Para mis envíos de código de golf en C, necesito una herramienta de procesamiento. Al igual que en muchos otros lenguajes, el espacio en blanco es irrelevante en su mayoría en la fuente C (¡pero no siempre!) - aún hace que el código sea mucho más comprensible para los humanos. Un programa C completamente desarrollado que no contiene un solo espacio en blanco redundante a menudo es apenas legible.
Por lo tanto, me gusta escribir mi código en C para un envío de código de golf que incluye espacios en blanco y, a veces, comentarios, para que el programa mantenga una estructura comprensible mientras escribo. El último paso es eliminar todos los comentarios y espacios en blanco redundantes. Esta es una tarea tediosa y sin sentido que realmente debe hacer un interno en un programa de computadora.
Tarea
Escriba un programa o función que elimine comentarios y espacios en blanco redundantes de alguna fuente de C "pre-golf" de acuerdo con las siguientes reglas:
- A
\
(barra invertida) como el último carácter de una línea es una continuación de línea . Si encuentra esto, debe tratar la siguiente línea como parte de la misma línea lógica (podría, por ejemplo, eliminar completamente la\
y la siguiente\n
(nueva línea) antes de hacer cualquier otra cosa) - Los comentarios solo usarán el formato de una línea, comenzando con
//
. Por lo tanto, para eliminarlos, ignora el resto de la línea lógica siempre que se encuentre//
fuera de un literal de cadena (consulte a continuación). - Los caracteres de
espacio en blanco son (espacio),
\t
(tabulación) y\n
(nueva línea, así que aquí el final de una línea lógica). Cuando encuentre una secuencia de espacios en blanco, examine los caracteres que no lo son. Si
- ambos son alfanuméricos o subrayados (rango
[a-zA-Z0-9_]
) o - ambos son
+
o - ambos son
-
o - el anterior es
/
y el siguiente es*
luego reemplace la secuencia con un solo espacio (
).
De lo contrario, elimine la secuencia por completo.
Esta regla tiene algunas excepciones :
- Las directivas de preprocesador deben aparecer en sus propias líneas en su salida. Una directiva de preprocesador es una línea que comienza con
#
. - Dentro de un literal de cadena o literal de caracteres , no debe eliminar ningún espacio en blanco. Cualquier
"
(comilla doble) /'
(comilla simple) que no esté precedida directamente por un número impar de barras invertidas (\
) comienza o finaliza una cadena literal / carácter literal . Le garantizamos que los literales de cadena y caracteres terminan en la misma línea que comenzaron. literales de cadena y literales de caracteres no se pueden anidar, por lo que un'
interior de un literal de cadena , así como"
el interior de un carácter literal no tienen ningún significado especial.
- ambos son alfanuméricos o subrayados (rango
Especificación de E / S
La entrada y la salida deben ser secuencias de caracteres (cadenas) que incluyen caracteres de nueva línea o matrices / listas de cadenas que no contienen caracteres de nueva línea. Si elige usar matrices / listas, cada elemento representa una línea, por lo que las nuevas líneas están implícitas después de cada elemento.
Puede suponer que la entrada es un código fuente de programa C válido. Esto también significa que solo contiene caracteres ASCII imprimibles, pestañas y líneas nuevas. Se permite un comportamiento indefinido en la entrada con formato incorrecto.
Espacio inicial y final / líneas vacías son no permitidos .
Casos de prueba
entrada
main() { printf("Hello, World!"); // hi }
salida
main(){printf("Hello, World!");}
entrada
#define max(x, y) \ x > y ? x : y #define I(x) scanf("%d", &x) a; b; // just a needless comment, \ because we can! main() { I(a); I(b); printf("\" max \": %d\n", max(a, b)); }
salida
#define max(x,y)x>y?x:y #define I(x)scanf("%d",&x) a;b;main(){I(a);I(b);printf("\" max \": %d\n",max(a,b));}
entrada
x[10];*c;i; main() { int _e; for(; scanf("%d", &x) > 0 && ++_e;); for(c = x + _e; c --> x; i = 100 / *x, printf("%d ", i - --_e)); }
salida
x[10];*c;i;main(){int _e;for(;scanf("%d",&x)>0&&++_e;);for(c=x+_e;c-->x;i=100/ *x,printf("%d ",i- --_e));}
entrada
x; #include <stdio.h> int main() { puts("hello // there"); }
salida
x; #include<stdio.h> int main(){puts("hello // there");}
input (un ejemplo del mundo real)
// often used functions/keywords: #define P printf( #define A case #define B break // loops for copying rows upwards/downwards are similar -> macro #define L(i, e, t, f, s) \ for (o=i; o e;){ strcpy(l[o t], l[o f]); c[o t]=c[s o]; } // range check for rows/columns is similar -> macro #define R(m,o) { return b<1|b>m ? m o : b; } // checking for numerical input is needed twice (move and print command): #define N(f) sscanf(f, "%d,%d", &i, &j) || sscanf(f, ",%d", &j) // room for 999 rows with each 999 cols (not specified, should be enough) // also declare "current line pointers" (*L for data, *C for line length), // an input buffer (a) and scratch variables r, i, j, o, z, c[999], *C, x=1, y=1; char a[999], l[999][999], (*L)[999]; // move rows down from current cursor position D() { L(r, >y, , -1, --) r++ ? strcpy(l[o], l[o-1]+--x), c[o-1]=x, l[o-1][x]=0 : 0; c[y++] = strlen(l[o]); x=1; } // move rows up, appending uppermost to current line U() { strcat(*L, l[y]); *C = strlen(*L); L(y+1, <r, -1, , ++) --r; *l[r] = c[r] = 0; } // normalize positions, treat 0 as max X(b) R(c[y-1], +1) Y(b) R(r, ) main() { for(;;) // forever { // initialize z as current line index, the current line pointers, // i and j for default values of positioning z = i = y; L = l + --z; C = c + z; j = x; // prompt: !r || y/r && x > *C ? P "end> ") : P "%d,%d> ", y, x); // read a line of input (using scanf so we don't need an include) scanf("%[^\n]%*c", a) // no command arguments -> make check easier: ? a[2] *= !!a[1], // numerical input -> have move command: // calculate new coordinates, checking for "relative" N(a) ? y = Y(i + (i<0 | *a=='+') * y) , x = X(j + (j<0 || strchr(a+1, '+')) * x) :0 // check for empty input, read single newline // and perform <return> command: : ( *a = D(), scanf("%*c") ); switch(*a) { A 'e': y = r; x = c[r-1] + 1; B; A 'b': y = 1; x = 1; B; A 'L': for(o = y-4; ++o < y+2;) o<0 ^ o<r && P "%c%s\n", o^z ? ' ' : '>', l[o]); for(o = x+1; --o;) P " "); P "^\n"); B; A 'l': puts(*L); B; A 'p': i = 1; j = 0; N(a+2); for(o = Y(i)-1; o<Y(j); ++o) puts(l[o]); B; A 'A': y = r++; strcpy(l[y], a+2); x = c[y] = strlen(a+2); ++x; ++y; B; A 'i': D(); --y; x=X(0); // Commands i and r are very similar -> fall through // from i to r after moving rows down and setting // position at end of line: A 'r': strcpy(*L+x-1, a+2); *C = strlen(*L); x = 1; ++y > r && ++r; B; A 'I': o = strlen(a+2); memmove(*L+x+o-1, *L+x-1, *C-x+1); *C += o; memcpy(*L+x-1, a+2, o); x += o; B; A 'd': **L ? **L = *C = 0, x = 1 : U(); y = y>r ? r : y; B; A 'j': y<r && U(); } } }
salida
#define P printf( #define A case #define B break #define L(i,e,t,f,s)for(o=i;o e;){strcpy(l[o t],l[o f]);c[o t]=c[s o];} #define R(m,o){return b<1|b>m?m o:b;} #define N(f)sscanf(f,"%d,%d",&i,&j)||sscanf(f,",%d",&j) r,i,j,o,z,c[999],*C,x=1,y=1;char a[999],l[999][999],(*L)[999];D(){L(r,>y,,-1,--)r++?strcpy(l[o],l[o-1]+--x),c[o-1]=x,l[o-1][x]=0:0;c[y++]=strlen(l[o]);x=1;}U(){strcat(*L,l[y]);*C=strlen(*L);L(y+1,<r,-1,,++)--r;*l[r]=c[r]=0;}X(b)R(c[y-1],+1)Y(b)R(r,)main(){for(;;){z=i=y;L=l+--z;C=c+z;j=x;!r||y/r&&x>*C?P"end> "):P"%d,%d> ",y,x);scanf("%[^\n]%*c",a)?a[2]*=!!a[1],N(a)?y=Y(i+(i<0|*a=='+')*y),x=X(j+(j<0||strchr(a+1,'+'))*x):0:(*a=D(),scanf("%*c"));switch(*a){A'e':y=r;x=c[r-1]+1;B;A'b':y=1;x=1;B;A'L':for(o=y-4;++o<y+2;)o<0^o<r&&P"%c%s\n",o^z?' ':'>',l[o]);for(o=x+1;--o;)P" ");P"^\n");B;A'l':puts(*L);B;A'p':i=1;j=0;N(a+2);for(o=Y(i)-1;o<Y(j);++o)puts(l[o]);B;A'A':y=r++;strcpy(l[y],a+2);x=c[y]=strlen(a+2);++x;++y;B;A'i':D();--y;x=X(0);A'r':strcpy(*L+x-1,a+2);*C=strlen(*L);x=1;++y>r&&++r;B;A'I':o=strlen(a+2);memmove(*L+x+o-1,*L+x-1,*C-x+1);*C+=o;memcpy(*L+x-1,a+2,o);x+=o;B;A'd':**L?**L=*C=0,x=1:U();y=y>r?r:y;B;A'j':y<r&&U();}}}
Este es el código de golf , por lo que gana la respuesta válida más corta (en bytes).