/* erstmal etwas code, erläuterungen folgen weiter unten. */
int ctod(char c) {
if (c>='0' && c<='9') { return (int)(c-'0'); }
if (c>='a' && c<='z') { return (int)(c-'a'+10); }
if (c=>'A' && c<='Z') { return (int)(c-'A'+10); }
/* hier könnte man was zur fehlerbehandlung einfügen */
/* z.b. -1 zurückgeben oder eine exception werfen. */
return -1;
}
irgendwo in main:
char* s,p,q;
int b,i,n,l;
double d = 0;
boolean neg = FALSE;
/* zahl einlesen und in s schreiben */
/* basis einlesen und in b schreiben */
while(*s == ' ' || *s == '\t') { s++; }
if (*s == '-') { s++; neg=TRUE; }
p=s;
i=0;
while(*p != '.') { p++; }
q=p;
while(p-- != s) {
if((n=ctod(*p)) >= b) { /* fehler in eingabe, abbruch */ }
d=d+pow((double)n, (double)i++);
}
i=0;
while(*++q != '\0') {
if((n=ctod(*p)) >=b) { /* siehe oben */ }
d=d+pow((double)n, (double)(0 - ++i));
}
if(neg) { d=d*-1; }
printf("%s mit Basis %d zur Basis 10 ist %f\n", s, b, d); // cout sucks0rz! >:)
/*
anm.:
kleine aufwärmübung in pointerarithmetik.
sollte der compiler warnungen ausspucken, typecasts einfügen.
dieser code ist bewußt unsauber, läßt sich dafür vom compiler
aber einfacher optimieren. fehlerbehandlung fehlt.
das größere problem in dem gezeigten programm dürfte die behandlung
der formulardaten sein (auch da fehlt einiges an fehlerbehandlung).
daher vorschlag: erstmal debug-ausgabe einbauen, damit man sieht
mit welchen werten der hauptteil des programms eigentlich arbeitet.
erkl.:
statt ints zur berechnung der position im string verwende ich
direkt pointer, die mit ++ und -- jeweils ein zeichen verschoben
werden (funktioniert NICHT mit unicode bzw. doppelbyte strings -
das ist jedoch hier irrelevant da die zeichen [^a-zA-Z0-9] ungültig
sind).
wichtig ist beim lesen der while-schleifen der unterschied zwischen
++p und p++ - postincrement und preincrement (bzw -- -> decrement).
while(++q != '\0') bricht ab sobald der pointer q auf das nullbyte
(ende des strings) zeigt (evtl. sicherung einbauen, falls nicht
garantiert ist, daß s mit einem \0 endet).
while(p-- != s) bricht ab, *NACHDEM* p das erste mal auf s gezeigt
*HAT*, damit das erste zeichen auch geparst wird.
grund:
p sei s+1. p-- wird erst nach dem vergleich ausgewertet.
p != s trifft zu, schleife läuft weiter.
q sei zeige nach ende der schleife auf das zeichen 1 vor dem
nullbyte. vor dem nächsten durchlauf wird q um eins erhöht und
dann das zeichen bei q mit \0 verglichen. der vergleich trifft
zu, die schleife wird abgebrochen, \0 wird nicht mehr geparst.
analoges gilt für i. merke:
x++: wert von x verwenden, danach x erhöhen.
++x: x erhöhen, danach wert von x verwenden.
warnung: wenn man den speicher für s von hand mit malloc reserviert,
sollte ein weiterer pointer benutzt werden, der nicht verschoben
wird. ansonsten läßt sich der speicher bei programmende nicht wieder
freigeben, es entsteht ein leak.
für weitere anwendung in einem richtigen programm anstatt einer
übungsaufgabe, läßt sich das ganze ohne große änderungen auch in
eine funktion packen:
boolean atof_base(char* a, int b, double* r) {
/* b aus den variablendeklarationen entfernen */
s=a;
/* rest von oben, bei fehlern "return FALSE;", statt fprint: */
*r = d;
return TRUE;
}
ach ja, auch boolean ist eventuell nicht bei jedem compiler bekannt.
falls nicht, kann man statt dessen ein typedef einrichten:
typedef int boolean;
#define FALSE 0
#define TRUE 1
der code ist nicht getestet, vermutlich nicht sicher und wird
garantiert jeden professor oder tutor in den wahnsinn treiben.
wer (tipp)fehler findet, darf sie korrigieren. ;)
-- Elberet
*/