c - 424 notwendiges Zeichen
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define O(X) g=o();g=o() X g;u(g);break;
char*p=NULL,*b;size_t a,n=0;float g,s[99];float o(){return s[--n];};
void u(float v){s[n++]=v;};int main(){getdelim(&p,&a,EOF,stdin);for(;;){
b=strsep(&p," \n\t");if(3>p-b){if(*b>='0'&&*b<='9')goto n;switch(*b){case 0:
case EOF:printf("%f\n",o());return 0;case'+':O(+)case'-':O(-)case'*':O(*)
case'/':O(/)}}else n:u(atof(b));}}
Angenommen, Sie haben eine neue Libc, die getdelim
in stdio.h aufgenommen werden kann. Der Ansatz ist direkt, die gesamte Eingabe wird in einen Puffer eingelesen, dann wird mit der strsep
Länge und dem Anfangszeichen getoken und die Klasse der einzelnen Zeichen bestimmt. Es gibt keinen Schutz vor schlechten Eingaben. Füttere es mit "+ - * / + - ...", und es wird fröhlich "unter" dem Stapel Zeug aus dem Speicher entfernen, bis es einen Fehler aufweist. Alle Nicht-Operatoren werden als Gleitkommazahlen interpretiert, atof
was bedeutet, dass der Wert Null ist, wenn sie nicht wie Zahlen aussehen.
Lesbar und kommentiert:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *p=NULL,*b;
size_t a,n=0;
float g,s[99];
float o(){ /* pOp */
//printf("\tpoping '%f'\n",s[n-1]);
return s[--n];
};
void u(float v){ /* pUsh */
//printf("\tpushing '%f'\n",v);
s[n++]=v;
};
int main(){
getdelim(&p,&a,EOF,stdin); /* get all the input */
for(;;){
b=strsep(&p," \n\t"); /* now *b though *(p-1) is a token and p
points at the rest of the input */
if(3>p-b){
if (*b>='0'&&*b<='9') goto n;
//printf("Got 1 char token '%c'\n",*b);
switch (*b) {
case 0:
case EOF: printf("%f\n",o()); return 0;
case '+': g=o(); g=o()+g; u(g); break;
case '-': g=o(); g=o()-g; u(g); break;
case '*': g=o(); g=o()*g; u(g); break;
case '/': g=o(); g=o()/g; u(g); break;
/* all other cases viciously ignored */
}
} else { n:
//printf("Got token '%s' (%f)\n",b,atof(b));
u(atof(b));
}
}
}
Validierung:
$ gcc -c99 rpn_golf.c
$ wc rpn_golf.c
9 34 433 rpn_golf.c
$ echo -4 5 + | ./a.out
1.000000
$ echo 5 2 / | ./a.out
2.500000
$ echo 5 2.5 / | ./a.out
2.000000
Heh! Muss irgendetwas damit zitieren *
...
$ echo "5 1 2 + 4 * 3 - +" | ./a.out
14.000000
$ echo "4 2 5 * + 1 3 2 * + /" | ./a.out
2.000000
und mein eigener Testfall
$ echo "12 8 3 * 6 / - 2 + -20.5 " | ./a.out
-20.500000
~
. :-P