AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...
das mit der string-änderung sehe ich bei der rekursion auch nich als das problem dabei an - es ist die ratio. er will ja zwingend, dass ne ratio zurück gegeben wird, und das wird schlicht und ergreifend nix, wenn du das in teilschritten machst. hab ich ja weiter oben schonma durchgerechnet:
nun gut. mal paar lösungsansätze:
ich habs ja schon angemerkt, dass du die ratio ned auffängst und weiterverarbeitest, macht das ganze unterfangen recht.... sinnlos ^^ und nebenher: ne ratio kann man so nich berechnen. stell dir vor, du würdest die irgendwie weiterverarbeiten. zum bsp ratio = (ratio + encode_runlength(s+i)) / 2; -> so ala durchschnitt der ratio bilden. dann hättest du bei ABBCCCCCCCCCC -> AB2C10 -> 3*100/13 = 23,08 -> 2*100/13 = (15,38 + 23,08)/2 = 19,23 -> 1*100/13 = (7,69 + 19.23)/2 = 13,46%
so, demgegenüber steht nun die tatsächliche verkürzung von 13 auf 6 zeichen -> 6*100/13 = 46,15%
wenn man die ratien simpel addiert, kämen wir auf ... wow 46,15 ^^ ok, also scheint man die einfach nur addieren zu brauchen, ok. das war mir bisher nich bewusst. dann scheints also doch auch so zu gehn ^^ der übersichtlickheit wegen hätt ichs aber dennoch nicht grad rekursiv gelöst.
meine grundidee dazu war die folgende:
man reduziert alle vorkommen wie gehabt und schreibt das reduzierte immer an den anfang, während man quasi am ende liest. gott, das lässt sich blöd erklären, ich versuchs mal visualisiert darzustellen. hierbei soll jetzt
unterstrichen der lese-zeiger sein und
fett der schreib-zeiger:
Code:
[COLOR=red][U][B]A[/B][/U]AAABBBCCCCCCCCDEABBBBDDDDDDDD -> er zählt 4 A's und schreibt sie an den anfang. lese-zeiger is beim ersten B, schreiber hinterm A4
A4[COLOR=seagreen][B]A[/B]A[COLOR=red][U]B[/U]BBCCCCCCCCDEABBBBDDDDDDDD_ -> er zählt 3 B's und schreibt sie
A4B3[COLOR=seagreen][B]B[/B]BB[COLOR=red][U]C[/U]CCCCCCCDEABBBBDDDDDDDD_ -> er zählt 8 C's und schreibt sie
A4B3C8[COLOR=seagreen][B]B[/B]CCCCCCCC[COLOR=red][U]D[/U]EABBBBDDDDDDDD_ -> er zählt ein D und schreibt es
A4B3C8D[COLOR=seagreen][B]C[/B]CCCCCCCD[COLOR=red][U]E[/U]ABBBBDDDDDDDD_ -> er zählt ein E und schreibt es
A4B3C8DE[COLOR=seagreen][B]C[/B]CCCCCCDE[COLOR=red][U]A[/U]BBBBDDDDDDDD_ -> er zählt ein A und schreibt es
A4B3C8DEA[COLOR=seagreen][B]C[/B]CCCCCDEA[COLOR=red][U]B[/U]BBBDDDDDDDD_ -> er zählt 4 B's und schreibt sie
A4B3C8DEAB4[COLOR=seagreen][B]C[/B]CCCDEABBBB[COLOR=red][U]D[/U]DDDDDDD_ -> er zählt 8 D's und schreibt sie
A4B3C8DEAB4D8[COLOR=seagreen][B]C[/B]CDEABBBBDDDDDDDD[COLOR=red]_ -> er erkennt das ende und "kopiert" es
A4B3C8DEAB4D8_[COLOR=seagreen][B]C[/B]DEABBBBDDDDDDDD[COLOR=red]_
da erkennt mans hoffentlich ganz gut, dass die sich ned in die quere kommen und das klappen dürfte.
so wegen dieser c_by_ref geschichte: hab hier nochmal nen link gefunden -
The Use of * and & in C/C++ . ein & stellt also die adresse der variablen dar. ah ok, jetz hab ichs glaube:
References, pointers and addresses are closely related concepts. Addresses are addresses in computer memory (typically the address in memory where the value of some variable is stored), e.g. (in hexadecimal) 0xAB32C2. Pointers are variables which hold addresses, and so "point to" memory locations (and thus to the values of variables). Conceptually, reference variables are basically pointers by another name (but may not be instantiated as such by the compiler).
also die adresse an sich ist der punkt im speicher, wo meine variable steht. ein zeiger (*p) zeigt nun auf diese adresse. der zeiger selbst ist eine variable, die an einer anderen speicher adresse steht, deren wert die adresse der variablen ist, auf die er zeigt.
Code:
int i = 15;
int *p = &i; // wenn mich jetz nich alles täuscht. mit & bekommt man die adresse einer variablen
Adresse|Wert|Var-Name
123|15|i
...||
234|123|p
der knackpunkt ist nun folgender:
übergibst du nun den zeiger an eine funktion, so wird dieser wieder nur kopiert. man hat also quasi sowas hier dann:
Code:
void fkt(int *q) {}
void main(void) {
int i = 15;
int *p = &i;
fkt(p);
}
Adresse|Wert|Var-Name
123|15|i
...||
234|123|p
...||
345|123|q
so, jetz kommt das große überlegen. weil mir erscheint das auf anhieb garnich schlecht ^^ mit q kann ich auf die speicheradresse zugreifen und den wert darin ändern, so eigentlich. das machen wir ja die ganze zeit. veränder ich q (iteriere durch den string) bleibt p in der main davon unberührt. also während ich in der funktion q auf stelle 5 habe, ist p immernoch am anfang. das wäre für die weitere verwendung zum dekodieren ganz praktisch so
gut, jetzt mal zu dem & ding da. mit & gibt man der variablen wohl nen 2. namen, mal blöde gesagt. also quasi so in etwa:
Code:
void fkt(int &q) {}
void main(void) {
int i = 15;
int *p = &i;
fkt(p);
}
Adresse|Wert|Var-Name
123|15|i
...||
234|123|p,q
wobei ich hier eben grad nich weis, ob das schon der springende punkt ist. denn im urpsungszenario siehts ja so aus:
Code:
void fkt(int &q) {}
void main(void) {
int i = 15;
fkt(i);
}
Adresse|Wert|Var-Name
123|15|i,q
also man übergibt die variable an sich und hat in der funktion eine referenz, quasi einen zweiten namen für ein und die selbe speicherstelle. verändere ich hier nun q in der funktion, bleibt die änderung auch ausserhalb bestehen. bei normalen variablen. ich werfe i rein und die funktion krallt sich die adresse von i für q. ja genau. will ich nun aber eben einen zeiger übergeben, klappt das so nich mehr. wobei wir wieder bei dem vorletzten bsp wären, wo ich ja p als zeiger auf i baue und der funktion übergeb. was passiert hier? mal überlegen. ich werfe p in die funktion und q krallt sich dessen adresse. also scheint meine tabelle da oben auch zu stimmen. p und q sind variablen namen für ein und die selbe speicheradresse.
ok, gut so weit. wenn ich jetzt innerhalb der funktion mit q rum iteriere (also hier geh ich ma nich vom i ausm bsp aus, da gibts nix zu iterieren ^^, sondern von unsrem char *s ^^), dann zeigt auch ausserhalb p auf diese position. wöllte ich dann also danach unseren string per zeiger an die decode funke übergeben, müsste ich ihn erst wieder auf den anfang setzen.
so, um nun auf den wert der variablen hinter der adresse zu kommen, muss man wieder den * benutzen. also int *p; p = &i; dann ist p die adresse von i und *p der wert, wenn ichs richtig verstanden hab.
nun gut, jetz will ich mal dieses schon genannte (
Pointer-to-Pointer and Reference-to-Pointer ) bsp durchprobieren: teil1:
Code:
int g_One = 1; //global variable
void func(int* pInt) {
pInt=&g_One;
}
int main() {
int nvar=2;
int* pvar=&nvar;
func(pvar);
std::cout<<*pvar<<std::endl; //Will still show 2
return 0;
}
Adresse|Wert|Var-Name
123|1|g_One
124|2|nvar
...||
234|124|pvar
...||
345|234|pInt
das müssts sein jetz. er versucht, in der funktion den wert für die ausserhalb der funktion stehende pvar-variable zu ändern. klappt aber nich. ja genau, das is genau das, was wir hier schon durchgegangen sin: pInt (in der funktion) kopiert nur pvar. man ändert also die kopie (welche am ende der funktion wieder verfällt) und nicht das original. würde man innerhalb der funktion noch ne ausgabe machen, würde er tatsächlich den wert von g_One ausgeben, weil pInt jetzt darauf zeigt. pInt ist aber eben nicht pvar, sondern nur eine kopie davon. pvar selber bleibt unberührt davon.
sein 2. bsp:
Code:
void func(int** ppInt) {
//Modify the pointer ppInt points to
*ppInt=&g_One;
//You can also allocate memory, depending on your requirements
*ppInt=new int;
//Modify the variable *ppInt points to
**ppInt=3;
}
int main() {
int nvar=2;
int* pvar=&nvar;
func(&pvar);
....
return 0;
}
Adresse (wo)|Wert (was)|Var-Name
123|2|nvar
...||
234|123|pvar
...||
345|234|ppInt
hmm. er übergibt nun also die adresse vom pointer an die funktion. und die funktion greift dank ** was auf? den wert oder? * von & wäre die adresse von pvar meines erachtens nach. und der * dieser adresse (der * vom * -> **) müsste nun doch der wert sein. den erklärungen im text danach zu folge dürfte das stimmen. mit *ppInt ändere ich die adresse, auf die pvar (also auch ausserhalb) zeigt, mit ** würde ich dann ändern "what pvar points to", also auf was pvar zeigt. ja genau, nich wohin es zeigt, sondern auf was es zeigt - den wert. ändere ich also nun in der funktion was an ppInt, dann hat das nach aussen keinerlei auswirkung, da es nur eine kopie ist. hmm, warscheinlich muss man das ganze in der tabelle sogar erweitern, da es ne "tiefere" kopie ist:
Adresse (wo)|Wert (was)|Var-Name
123|2|nvar
...||
234|123|pvar
...||
345|2|**ppInt
346|123|*ppInt
347|234|ppInt
wobei das auch nich sehr schlüssig aussieht. die 2 neuen zeilen hier sind warscheinlich "einfach" bestandteil von ppInt - mitkopiert. ich ändere also die "tieferliegenden bestandteile" von ppInt, nicht aber pvar oder gar nvar. also: was ich in der funktion änder, hat hier auch wieder nur in der funktion auswirkung. die äusseren variablen bleiben davon unberührt.
wad macht nun aber das 3, bsp wieder anders? ma schauen, dann erstma schluss ><
Code:
int g_One=1; //global variable
void func(int*& rpInt)
{
//Modify what pvar is pointing to, to g_One
rpInt=&g_One;
//You can also allocate memory, depending on your requirements
rpInt=new int;
//Modify the variable rpInt points to
*rpInt=3;
}
int main()
{
int nvar=2;
int* pvar=&nvar;
func(pvar);
....
return 0;
}
Adresse (wo)|Wert (was)|Var-Name
123|1|g_One
124|2|nvar
...||
234|124|pvar, rpInt
hier wird nun also eine referenz des zeigers (*&) pvar angelegt. man bekommt also tatsächlich den zeiger pvar innerhalb der funktion und keine kopie davon. jetzt kann ich wieder ganz normal innerhalb der funktion die adresse für pvar ausserhalb ändern - und auch den wert der variablen ausserhalb, auf die pvar zeigt (also nvar) kann ich von innen her ändern.
gut gut, ich glaube, die letzte version wäre für uns ganz brauchbar oder? so hab ichs gestern auch schon versucht, aber ohne dieses durchexerzieren und das tiefere verständnis. nu wäre ich gespannt, obs mir jetz besser gelingen würde ><
nun gut, genug geschrieben, ich hoffe ihr kamt alle mit und konntet mir folgen. und vorallem hoffe ich, das ich ned allzuviel bull *piep* verzapft hab hier xD