Contexte
Pour mes soumissions de code-golf en C, j'ai besoin d'un outil de traitement. Comme dans de nombreux autres langages, les espaces blancs ne sont généralement pas pertinents dans la source C (mais pas toujours!) - rendent le code beaucoup plus compréhensible pour les humains. Un programme C entièrement joué qui ne contient pas un seul espace redondant est souvent à peine lisible.
Par conséquent, j'aime écrire mon code en C pour une soumission de code-golf comprenant des espaces et parfois des commentaires, afin que le programme conserve une structure compréhensible lors de l'écriture. La dernière étape consiste à supprimer tous les commentaires et les espaces blancs redondants. C'est une tâche fastidieuse et insensée qui devrait vraiment être effectuée par un stagiaire dans un programme informatique.
Tâche
Écrivez un programme ou une fonction qui élimine les commentaires et les espaces blancs redondants d'une source C "pré-golfée" selon les règles suivantes:
- Un
\
(barre oblique inversée) comme dernier caractère d'une ligne est une continuation de ligne . Si vous trouvez cela, vous devez traiter la ligne suivante comme faisant partie de la même ligne logique (vous pouvez par exemple supprimer complètement le\
et le suivant\n
(nouvelle ligne) avant de faire quoi que ce soit d'autre) - Les commentaires utiliseront uniquement le format d'une ligne, en commençant par
//
. Donc, pour les supprimer, vous ignorez le reste de la ligne logique partout où vous rencontrez en//
dehors d'un littéral de chaîne (voir ci-dessous). - Les caractères d'
espacement sont (espace),
\t
(tabulation) et\n
(nouvelle ligne, donc voici la fin d'une ligne logique). Lorsque vous trouvez une séquence d'espaces blancs, examinez les caractères non blancs qui l'entourent. Si
- les deux sont alphanumériques ou soulignés (plage
[a-zA-Z0-9_]
) ou - les deux sont
+
ou - les deux sont
-
ou - celui qui précède est
/
et le suivant est*
puis remplacez la séquence par un seul caractère espace (
).
Sinon, supprimez complètement la séquence.
Cette règle comporte quelques exceptions :
- Les directives du préprocesseur doivent apparaître sur leurs propres lignes dans votre sortie. Une directive de préprocesseur est une ligne commençant par
#
. - À l'intérieur d'un littéral de chaîne ou d' un littéral de caractère , vous ne devez supprimer aucun espace. Tout
"
(guillemet double) /'
(guillemet simple) qui n'est pas directement précédé d'un nombre impair de barres obliques inverses (\
) démarre ou termine un littéral de chaîne / un littéral de caractère . Vous êtes assuré que les littéraux de chaîne et de caractère se terminent sur la même ligne qu'ils ont commencée. les littéraux de chaîne et les littéraux de caractère ne peuvent pas être imbriqués, donc l''
intérieur d'un littéral de chaîne , ainsi que l'"
intérieur d'un littéral de caractère n'ont pas de signification particulière.
- les deux sont alphanumériques ou soulignés (plage
Spécifications d'E / S
L'entrée et la sortie doivent être soit des séquences de caractères (chaînes), y compris des caractères de nouvelle ligne, soit des tableaux / listes de chaînes qui ne contiennent pas de caractères de nouvelle ligne. Si vous choisissez d'utiliser des tableaux / listes, chaque élément représente une ligne, donc les sauts de ligne sont implicites après chaque élément.
Vous pouvez supposer que l'entrée est un code source de programme C valide. Cela signifie également qu'il ne contient que des caractères ASCII imprimables, des tabulations et des retours à la ligne. Un comportement non défini sur une entrée mal formée est autorisé.
Les espaces vides de début et de fin ne sont pas autorisés .
Cas de test
contribution
main() { printf("Hello, World!"); // hi }
production
main(){printf("Hello, World!");}
contribution
#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)); }
production
#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));}
contribution
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)); }
production
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));}
contribution
x; #include <stdio.h> int main() { puts("hello // there"); }
production
x; #include<stdio.h> int main(){puts("hello // there");}
entrée (un exemple du monde réel)
// 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(); } } }
production
#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();}}}
C'est le code-golf , donc la réponse valide la plus courte (en octets) l'emporte.