[C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

Mit Zeigern und Adressen kenne ich mich eh aus und was du in der ersten Hälfte deines Postings beschreibst, habe ja ich schon in meinem letzten erkannt und beschrieben. Jetzt sind wir uns auch bei der ratio einig: Die muss ja nur für jeden Schleifendurchlauf mit der Anzahl der Zeichen, die printf ausgibt (ist immer 2 oder 1 --> ok, die 1er Abfrage fehlt im aktuellen Code noch) aufaddiert werden. Am Ende sollte ich dann bei unserem konkreten string 13 in ratio stehen haben. Da kann ich dann den Prozentwert damit berechnen. Aber das hast du ja mittlerweile eh selber erkannt.

Und eine Variable mit vorangestelltem &-Operator im Funktionskopf fällt für uns leider wieder aufgrund der Vorgaben in der Aufgabenstellung weg:
Die Schnittstelle der Funktion muss eingehalten werden.
^^ Und die sieht nun einmal so aus: double encode_runlength(char *s) --> also mit *-Operator.

Ich müsste eigentlich im Moment nur eines wissen: Wie genau kann ich nach vollständiger Codierung (oder auch rundenweise, wenn ich auf die Positionen aufpasse) *s (hat ja den Originalstring als Inhalt) in encode_runlength() mit dem codierten string überschreiben?

Ich hätte es mal so probiert, aber dann gibt er nur A4 aus und dann kommt eine Windows-Fehlermeldung:
Code:
double encode_runlength(char *s) {
    int i=0, j=1, count=0, length=checkLength(s);
    double ratio=0.0; 

    while (*(s+i) != '\0') {
        if (*(s+i)!=*(s+j)) {
            printf("%c%d", *(s+i), (j-count));
            count=j;
            [COLOR=royalblue][B]*(s+k)=*(s+i); [/B][COLOR=seagreen]/* jeder zweite Index beginnend bei 0 bekommt Buchstaben */[B]
            *(s+l)=(j-count); [/B][COLOR=seagreen]/* jeder zweite Index beginnend bei 1 bekommt Zahl */[B]
            k+=2;
            l+=2;[/B]        }
        i++;
        j++;    
    }

    return ratio;
}
Von der Reihenfolge her sollten wir jedenfalls keine Probleme bekommen ...
1. *s enthält den Originalstring und ich gebe ihn aus
2. Dann wird der Inhalt von *s in der aufgerufenen Funktion encode_runlength() überschrieben und der neue Inhalt (die Codierung) ausgegeben.
3. Dann greife ich in decode_runlength() auf *s, das ja nun die Codierung als Inhalt hat, zu und bearbeite *s wieder.
4. Anschließend wird die Codierung in decode_runlength() wieder mit dem Originalstring überschrieben und ausgegeben.
 
Zuletzt bearbeitet:
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

asö, man muss also mit char* arbeiten, k. da man damit aber den string ausserhalb nicht beeinflussen kann, sondern nur ne lokale kopie hat, folgende (simple) idee: schreib deinen kodierten krempel in ne neue char* variable und rufe aus der encode funktion die decode funktion aus, mit dem neuen string als parameter xD

also quasi:
Code:
encode(s) {
    char* new_s;
    baue new_s zusammen;
    vergleiche die länge von new_s mit s für die ratio;
    decode(new_s);
    schmeiss die ratio zurück;
}

aber noch fix am rande ne geschichte, die mich doch intressiert. ich hatte ja grad mit dem *& rumgetüftelt und war hierbei zu diesem ergebnis gekommen:
Code:
#include <stdio.h>
#include <conio.h>

int checkLength(char *s) {
    int length=0;
    while (*(s+length) != '\0') length++;
    return length;
}

void encode_runlength(char *&s) {
    int i=0, counter = 0;

    while (*s != '\0') {
        [B]//*s = (char)((int)*s + 1);[/B]
        printf("%c", (char)((int)*s + 1));
        s++;
        i++;
    }
}

int main(void) {
    char *str = "AAAABBBCCCCCCCCDEABBBBDDDDDDDD";
    double ratio;

    printf("Original:   %s\n", str);
    printf("Codiert:    ");
    encode_runlength(str);
    //ratio = (double)counter * 100 / length;
    printf("\nVerk%crzung: %s\n", 129, str);
    printf("Decodiert:\n\n");

    getch();
    return 0;
}
habs quasi erstma nur entkernt. er sollte im endeffekt nur erstmal aus allen A's B's machen usw usf. das ganze klappt auch wunderbar, wenn ich die fette zeile weglass. also reines lesen geht. sobald ichs aber schreiben will (was laut dem link da ja angeblich geht), schmiert er mit nem laufzeitfehler ab - schreibverletzung bla. also er kann an der stelle nich schreiben oO - warum? weis das einer?
 
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

^^ Ja, einen weiteren string verwenden, um darin die Codierung zu speichern, auf die Idee kommt bei dem Beispiel wohl jeder sofort, aber das schließt doch die Aufgabenstellung aus?!
Die codierte Zeichenkette wird direkt in die durch *s gegebene Zeichenkette gespeichert (keine weitere Zeichenkette verwenden).
Ich hätte es jetzt noch leicht umgeschrieben, um Variablen zu sparen, aber jetzt kommt gar keine Ausgabe mehr. Zumindest solltest du jetzt sehen, worauf genau ich hinaus will:
Code:
double encode_runlength(char *s) {
    int i=0, j=1, count=0;
    double ratio=0.0;

    for (i=0; *(s+i)!='\0'; i++) {
        if (*(s+i)==*(s+i+1)) {
            count++;
        } else {
            *(s+j-1)=*(s+i); [COLOR=seagreen]/* jeder zweite Index beginnend bei 0 bekommt Buchstaben */            *(s+j)=count; [COLOR=seagreen]/* jeder zweite Index beginnend bei 1 bekommt Zahl */            j+=2;
        }
    } 
    printf("%s\n", *s);

    return ratio;
}
BTW:
Ich hätte hier eine Lösung, die ich absolut gar nicht verstehe, aber vielleicht hilft dir das, mir zu helfen:
Code:
#include <stdio.h>
#include <math.h>

double encode_runlength (char *s) { /*funktion zum entcodieren */    
    int read = 0;
    int write = 0;
    char temp = '\0';
    int zaehler = 0;

    while(*(s+read) != '\0') {


        if(temp == *(s+read)) {
            zaehler++; 
        }
        else {
            if(temp != '\0'){
            *(s+write)= temp;
            write++;
            if(temp >1) {
                *(s+write) = zaehler + '0';
                write++;
                }
            }
            temp = *(s+read);
            zaehler = 1;    
        }
        read++; 
    }
    
    *(s+write)= temp;
            write++;
            if(temp >1) {

            *(s+write) = zaehler + '0';
            write++;
            }
            *(s+write)= '\0';

    return read?(write+0.0)/read:0.0;
}

int get_decoded_length(char *s){
    int len=0;
    int    zaehler=0;
    while(*s!=0){
        if(*s<'0'||*s>'9'){
            if(zaehler!=0){
                len+=zaehler-1;
                zaehler=0;
            }
            len++;
        }else{
            zaehler*=10;
            zaehler+=*s-'0';
        }
        s++;
    }
    if(zaehler!= 0){
        len+=zaehler-1;
        zaehler=0;
    }
    return len;

}

int decode_runlength(char *s) {
    int len=get_decoded_length(s);
    int r=-1;
    int w=len;
    int zaehler=0;
    int pos=0;
    
    *(s+w--)='\0';
    
    while(*(s+(++r)));
    r--;
    
    while(w>=0){
        if(*(s+r)<'0'||*(s+r)>'9'){
            zaehler=zaehler?zaehler:1;
            while(zaehler--)
                *(s+(w--))=*(s+r);
            zaehler=0;
            pos=0;
        }else
            zaehler+=(*(s+r)-'0')*pow(10.0,pos++);
        r--;
    }
    return 0;
}

int main(int argc, char *argv[]) {

    char *s = argv[1];
    double eff;
    printf("Zeichenkette: %s\n",argv[1]);;
    eff = encode_runlength(s);
    printf("Lauflaengen-Codierung: %s  \n",s);
    printf("Effizienz: %f)\n",eff);
    decode_runlength(s);
    printf("Wieder Decodiert: %s\n",s);

return 0;
}
[EDIT]
Müsste das Überschreiben nicht gerade bei der rekursiven Lösung "am einfachsten" gehen, indem ich einfach so irgendwie sage:
Code:
double encode_runlength(char *s) {
    int i=0, j=1, k=0;

    while (*(s+i) != '\0') {
        if (*(s+i)!=*(s+j)) {
            if (j==1) {
                printf("%c", *(s+i));
            } else {
                printf("%c%d", *(s+i), j);
            }
            i=j;
            [COLOR=royalblue][B]*(s+k)=encode_runlength(s+i);[/B]            [COLOR=royalblue][B]k++;[/B]            break;
        }
        i++;
        j++;
    }
}
^^ ???
 
Zuletzt bearbeitet:
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

^^ Ja, einen weiteren string verwenden, um darin die Codierung zu speichern, auf die Idee kommt bei dem Beispiel wohl jeder sofort, aber das schließt doch die Aufgabenstellung aus?!
naja gut, sogesehn ist *s innerhalb der funktion ja schon eine kopie des *s aus der main. nimmt man einfach den, is ja wumps ^^ das prinzip bliebe gleich.

edit: wegen meinem speicherzugriffs problem: http://www.computerbase.de/forum/showthread.php?t=235869 die erste antwort lesen (den eigentlichen text kann man ignorieren ^^)... char *s = "abc" ist nen const char array - also unveränderbar -.- wie umgeht man das nu am dümmsten? ^^ die antwort danach is mal wieder klasse: "ah toll, weis ich bescheid bal bla." aber WIE er das genau löst, steht wieder ned da.
 
Zuletzt bearbeitet:
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

naja gut, sogesehn ist *s innerhalb der funktion ja schon eine kopie des *s aus der main. nimmt man einfach den, is ja wumps ^^ das prinzip bliebe gleich.
Ja, aber das ist ja genau das, was ich schon die ganze Zeit probiere (siehe Codes im vorigen Posting), oder?

Zum Laufen kriegen müsste ich es noch. Eine Windows-Fehlermeldung nutzt mir nichts ... ;)

[EDIT]
Code:
double encode_runlength(char *s) {
    int i=0, j=1, k=0;

    while (*(s+i) != '\0') {
        if (*(s+i)!=*(s+j)) {
            if (j==1) {
                [COLOR=royalblue][B]*(s+i)=printf("%c", *(s+i));[/B]            } else {
                [B][COLOR=royalblue]*(s+i)=printf("%c", *(s+i));
                *(s+i+1)=printf("%d", j);[/B]
            }
            i=j;
            encode_runlength(s+i);
            break;
        }
        i++;
        j++;
    }

    return 0;
}
^^ Wäre auch noch eine Variante, die mir für die rekursive Lösung einfällt, aber leider ebenfalls nicht funktioniert.

[EDIT2]
So, wollte es jetzt nur einmal für A4 schaffen, dass das wieder an den ersten beiden Positionen von *s gespeichert wird ...
Code:
double encode_runlength(char *s) {
    int i=0, j=1, counter=0;

    while (*(s+i) != '\0') {
        if (*(s+i)==*(s+i+1)) {
            *(s+j)=counter++;
        } 
        i++;
    }

    printf("%s", *s);

    return 0;
}
... aber nö, nicht einmal das geht! Ich werde hier noch verrückt!!! :wall:
 
Zuletzt bearbeitet:
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

hab jetz die ganze zeit gebastelt >< also aus der string definition muss man wohl ein char s[] = "bla" machen. mit char *s = "bla" funzt es nich, da der ganze rotz dann konstant is und man nix ändern kann.

was ich ja witzig find irgendwie: urplötzlich kann man doch in der funktion auch änderungen vornehmen, die ausserhalb erhalten bleiben. liegt vllt auch daran, das man ein "solides" array hat und keinen zeiger. hmm, das wirds sein! nuja, jedenfalls hab ichs jetz soweit, dass ers schön codiert und versuch mich grad an der decodierung. etwas mehr aufwand hat mich dann dieses blöde zahlen speichern gekostet. die einfache variante (zeichen schreiben, zahl schreiben) funzt ja leider nur bis zahl < 10. danach muss man die zahl ja ziffer für ziffer schreiben. da hab ich ganz schön gefriemelt he.

nuja, schaus dir mal an, ob du für dich was verwerten kannst:
Code:
#include <stdio.h>
#include <conio.h>

int checkLength(char *s) {
    int length=0;
    while (*(s+length) != '\0') length++;
    return length;
}

void decode_runlength(char *s) {
    int length = checkLength(s) - 1;

    while(length >= 0) {
        printf("%c", *(s + length));
        length--;
    }
    printf("\n");
}

double encode_runlength(char *s) {
    int i = 0, j, counter = 1, newLength = 0, length = checkLength(s);
    char akt;
    double ratio = 0;

    // leerer string
    if(*s == '\0') return ratio;

    // string der länge 1
    if(*(s + 1) == '\0') return 100;

    // bei längeren dann hier weiter
    while (*(s + i) != '\0') {                        // solange das nächste zeichen nicht das ende is...
        if(*(s + i) == *(s + i + 1)) counter++;                // wenn das aktuelle und das nächste zeichen gleich sind, zähle weiter
        else {                                                // ansonsten schreib die kodierte anzahl auf
            akt = *(s + i);
            //printf("\n%d %c gefunden", counter, akt);
            if(counter > 1) {                                    // wird was zusammengefasst?
                *(s + newLength) = akt;                                // schreibe das aktuelle zeichne
                j = 0;
                while(counter % 10 > 0) {                            // gefolgt von der anzahl
                    newLength++;
                    // blöderweise schreibt er die zahl auf diese weise rückwärts, also irgendwie umdrehn ><
                    if(j > 0) {
                        for(int k = 1; k <= j; k++) *(s + newLength - k + 1) = *(s + newLength - k);    // die vorrangegangenen ziffern aufrücken
                        *(s + newLength - j) = (char)((counter % 10) + 48);                                // und die neue vorndran setzen
                    } else *(s + newLength) = (char)((counter % 10) + 48);
                    counter /= 10;
                    j++;
                }
                newLength++;
            } else {
                *(s + newLength) = akt;                                // schreibe nur das aktuelle zeichen
                newLength++;
            }
            counter = 1;                                        // den zähler resetten (eins hat man immer)
        }
        i++;
    }
    *(s + newLength) = '\0';

    ratio = (double)newLength * 100 / length;
    return ratio;
}

int main(void) {
    char str[] = "AAAABBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDEABBBBDDDDDDDD";
    double ratio;

    printf("Original:   %s\n", str);
    ratio = encode_runlength(str);
    printf("Codiert:    %s\n", str);
    printf("Verk%crzung: %5.2f%%\n", 129, (100 - ratio));
    decode_runlength(str);
    printf("Decodiert:  %s", str);

    getch();
    return 0;
}
 
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

Naja, so wirklich rund läuft dein Code noch nicht. Lösche mal testweise ein paar deiner Unmengen "C"s und du wirst sehen, dass die Ausgabe schon wieder nicht mehr stimmt ...

Capture.JPG

Im Übrigen: Was soll denn jetzt hier konkret anders sein, als in unseren Code-Versionen zuvor? Du sagts, es geht nur mit s[], verwendest dann aber trotzdem überall *s ?!
 
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

die unmengen C's waren drin, um zu testen, ob er zahlen über 100 ordentlich darstellt. hat er getan. mit 2stelligen hab ichs aber nich mehr getestet :/

und wegen dem *s vs s[] - schau mal in die main - DA hab ichs ändern müssen. mach da mal wieder die ursprüngliche variante draus - dann bekommste speicherschutzverletzungsfehler oder wie das hieß. dann kannst du das s (bei mir str) nur lesen, aber nicht schreiben (ändern). und ändern muss mans zwangsläufig.

edit: ok, es lief bei 10er schrittigen zahlen nich, die hat er schlicht ignoriert. auch bei 102 zum bsp. da hat er die 2 gemerkt, dann hatte er 10 über - wech. habs jetz gelöst bekommen :D
Code:
#include <stdio.h>
#include <conio.h>

int checkLength(char *s) {
    int length=0;
    while (*(s+length) != '\0') length++;
    return length;
}

void decode_runlength(char *s) {
    int length = checkLength(s) - 1;

    while(length >= 0) {
        printf("%c", *(s + length));
        length--;
    }
    printf("\n");
}

double encode_runlength(char *s) {
    int i = 0, j, counter = 1, newLength = 0, length = checkLength(s);
    char akt;
    double ratio = 0;

    // leerer string
    if(*s == '\0') return ratio;

    // string der länge 1
    if(*(s + 1) == '\0') return 100;

    // bei längeren dann hier weiter
    while (*(s + i) != '\0') {                        // solange das nächste zeichen nicht das ende is...
        if(*(s + i) == *(s + i + 1)) counter++;                // wenn das aktuelle und das nächste zeichen gleich sind, zähle weiter
        else {                                                // ansonsten schreib die kodierte anzahl auf
            akt = *(s + i);
            if(counter > 1) {                                    // wird was zusammengefasst?
                *(s + newLength) = akt;                                // schreibe das aktuelle zeichne
                j = 0;
                while(counter > 0) {                                // gefolgt von der anzahl
                    newLength++;
                    // blöderweise schreibt er die zahl auf diese weise rückwärts, also irgendwie umdrehn ><
                    if(j > 0) {
                        for(int k = 1; k <= j; k++) *(s + newLength - k + 1) = *(s + newLength - k);    // die vorrangegangenen ziffern aufrücken
                        *(s + newLength - j) = (char)((counter % 10) + 48);                                // und die neue vorndran setzen
                    } else *(s + newLength) = (char)((counter % 10) + 48);
                    if(counter >= 10) counter /= 10;
                    else counter = 0;
                    j++;
                }
                newLength++;
            } else {
                *(s + newLength) = akt;                                // schreibe nur das aktuelle zeichen
                newLength++;
            }
            counter = 1;                                        // den zähler resetten (eins hat man immer)
        }
        i++;
    }
    *(s + newLength) = '\0';

    ratio = (double)newLength * 100 / length;
    return ratio;
}

int main(void) {
    char str[] = "AAAABBBCCCCCCCCCCDEABBBBDDDDDDDD";
    double ratio;

    printf("Original:   %s\n", str);
    ratio = encode_runlength(str);
    printf("Codiert:    %s\n", str);
    printf("Verk%crzung: %5.2f%%\n", 129, (100 - ratio));
    decode_runlength(str);
    printf("Decodiert:  %s", str);

    getch();
    return 0;
}
 
Zuletzt bearbeitet:
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

Ok, vielen Dank für die Mühe!!! :daumen:

Will jetzt aber trotzdem nicht einfach deinen Code 1:1 übernehmen und das Beispiel abhaken, weil ich schon glaube, zu verstehen, wie sich's programmieren lässt. Was ich gebraucht habe, war die Erkenntnis, dass das Feld in der main als s[] definiert werden muss.

Werde das Ganze entweder heute Nacht, oder morgen noch einmal alleine von vorne angehen und dann sehen wir eh, wie weit ich mit meinem jetzigen Wissen kommen. Zur Not melde ich mich noch einmal. Auf die Angabe bezogen, würden eh dir auch noch ein paar Dinge fehlen, wie z.B. dass es egal ist, ob Groß- und Kleinbuchstaben gemischt im String vorkommen, oder dass eben dieser an die main übergeben wird ... ;)

Again, thanks a lot!
 
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

an die main wird der string doch "übergeben" ^^ siehste ja auch in der umsetzung. encode(s); print(s); bla. also in der funktion wird der string geändert, so das in der main die änderung bestehen bleibt. das decodieren wird nur nochmal nen spaß. und groß/klein als eins betrachten sollte auch eher ne kleinigkeit sein *grübel*

aber selber tüfteln is natürlich immer besser :D
 
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

an die main wird der string doch "übergeben"
Ich meinte, was hier im Code auskommentiert ist ... ;)

[EDIT]
Bin jetzt mit der iterativen Variante so weit gekommen, dass er mir richtigerweise die ersten 13 Stellen von s[] mit der Codierung überschreibt. Allerdings habe ich ein Problem:
Wieso habe ich da diese verdammten Smilies anstatt meiner Buchstaben und Zahlen? Alles, was ich bis jetzt rausfinden konnte, ist, dass der Smilie offenbar das ASCII-Zeichen für 257 ist, nur wie/wo/warum komme ich je auf 257?

Capture.JPG

^^ Der Wertebereich von char geht zwar nur von 0 bis 255 (mit 257 würde ich da hinauskommen), aber das sollte doch auch locker ausreichen?! Die Buchstaben A bis z liegen im ASCII-Bereich von 65 bis 122 und mehr wie 255 gleiche Zeichen hintereinander hat mein Beispielstring ja eh nicht ...
Code:
#include <stdio.h>

int checkLength(char *s) {
    int length=0;

    while (*(s+length)!='\0') {
        length++;
    }

    return length;
}

double encode_runlength(char *s) {
    int i=0, j=1, k=0, count=0, length=checkLength(s);
    double ratio=0.0;

    while (*(s+i) != '\0') {
        if (*(s+i)!=*(s+j)) {
            if ((j-count)==1) {
                *(s+k)=printf("%c", *(s+i));
                k++;
                count=j;
            } else {
                *(s+k)=printf("%c", *(s+i));
                *(s+k+1)=printf("%d", (j-count));
                k+=2;
                count=j;
                ratio=(double)k;
            }            
        }
        i++;
        j++;
    }

    return ((ratio*100)/(double)length);
}

void check(char *s) {
    printf("%s\n", s);
}

int main(void) {
    char s[] = "AAAABBBCCCCCCCCDEABBBBDDDDDDDD";

    printf("Original:   %s", s);
    printf("\nCodiert:    ");
    printf("\nVerk%crzung: %.0lf %%\n\n", 129, (100-encode_runlength(s)));
    check(s);

    return 0;
}
BTW: Gerade noch was gesehen ...
Kann sein, dass ich das einfach nur falsch interpretiere, aber mir kommt's eben komisch vor: Im Debugger schaut's so aus, als würde er lauter hexadezimale(?) 1er an die ersten 13 Feldelemente, die ja richtigerweise überschrieben werden sollen, schreiben (vor dem Überschreiben standen da die hexadezimalen Werte für A bis D). Sollte da nicht A4 B3 usw. in Hex im Speicher stehen bzw. genau A4B3 usw. in der Spalte rechts?

Capture.JPG

[EDIT2]
Habe mir gerade den Inhalt der ersten 13 Feldelemente von *s in decode_runlength() mit Hilfe einer Schleife ausgeben lassen. Bei int/hex/oct bekomme ich dann zwar keine Smilies angezeigt, aber dafür bestätigt sich, was Visual Studio im Speicher anzeigt --> alle 13 Felder sind mit 1er aufgefüllt:
Code:
int decode_runlength(char *s) {
    int i=0;

    while (*(s+i)!='\0') {
        if (*(s+i)==1) {
            printf("s[%d]=%d\n", i, *(s+i));
        }
        i++;
    }
}
Capture.JPG

Lasse ich den Inhalt als char ausgeben, sind wir wieder bei den Smilies:
Capture.JPG

Wo sind meine A4, B3, etc.??? :huh:
 
Zuletzt bearbeitet:
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

Wo sind meine A4, B3, etc.??? :huh:
Code:
...
*(s+k)=printf("%c", *(s+i));
...

in den vorangegangenen beispielen hattest du das richtig verwendet - um rauszufinden, wieviel zeichen er schrieb. was passiert denn jetz hier? zum bsp schreibt er zu begin das A4. was gibt printf hier zurück? das A4? nein ;) er gibt ne 2 zurück, weil er 2 zeichen (A und 4) geschrieben hat. du hast nun also die länge des auf den bildschirm geschrieben textes an die erste stelle gespeichert anstelle des textes selbst. was meinste, wieso ich bei mir sonen riesen bromborium da reingebaut hatte? xD sicher nich aus langeweile :P

so, und wenn ich jetzt raten müsste, welche werte da drin stehn bei "AAAABBBCCCCCCCCDEABBBBDDDDDDDD" - da hat er nen A4 - also ne 2, nen B3 -> 2, C8 -> 2, D E und A jeweils 1, B und D am ende nochmals 2. müsste also sowas wie 22211122 drin stehn oder?

aaaaah ne, du schreibst erst den buchstaben und dann seperat die zahl. also steht da IMMER ne 1 ^^ bei A4 schreibt er A (printf returned länge 1) und dann 4 (wieder ne 1 returned) usw uwf. also:
Code:
11 11 11 1 1 1 11 11
A4 B3 C8 D E A B4 D8
 
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

^^ Ahhh ... :klatsch:

Okay, das bringt mich schon mal 50 % weiter. ;)

Die Ausgabe der Buchstaben kann man ja dann durch eine simple Zuweisung nach dem printf erreichen:

Capture.JPG
Code:
double encode_runlength(char *s) {
    int i=0, j=1, k=0, count=0, length=checkLength(s);
    double ratio=0.0;

    while (*(s+i) != '\0') {
        if (*(s+i)!=*(s+j)) {
            if ((j-count)==1) {
                printf("%c", *(s+i));
                [COLOR=royalblue][B]*(s+k)=*(s+i);[/B]                k++;
                count=j;
            } else {
                printf("%c%d", *(s+i), (j-count));
                [COLOR=royalblue][B]*(s+k)=*(s+i);[/B]                [COLOR=red][B]*(s+k+1)=*(s+i+1);[/B]                k+=2;
                count=j;
                ratio=(double)k;
            }            
        }
        i++;
        j++;
    }

    return ((ratio*100)/(double)length);
}
^^ Nur an der Ausgabe der Zahlen scheitert es noch. Dass die rote Zeile falsch ist, weiß ich. Die habe ich nur gemacht, damit wir wenigstens Buchstaben an den Positionen haben, wo die Zahlen hin sollen und nicht wieder irgendwelche Smilies, Copyrights, oder sonst was.

Für meine Logik würde *(s+k+1)=(j-count); den meisten Sinn machen, aber damit bekomme ich wieder alle möglichen lustigen Symbole ... :ugly:
Dabei ist doch j-count in jeder Runde genau das, wo die Zahl berechnet wird?!

[EDIT]
Hab's schon:
Code:
*(s+k+1)=(char)(j-count)+48;
Capture.JPG

^^ Du siehst, man kommt offenbar auch ohne dein ganzes "Bromborium" aus. ;)

PS: Muss ich nur noch den Müll nach der letzten Zahl wegbringen. Oder einfach danach irgendwie eine '\0' zuweisen ...

[EDIT2]
So, das wäre auch noch erledigt:
Code:
*(s+(int)ratio)='\0';
Capture.JPG

Ist ja jetzt wirklich nur mehr Zuweisen, Zuweisen, Zuweisen ... :D
 
Zuletzt bearbeitet:
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

[EDIT]
Hab's schon:
Code:
*(s+k+1)=(char)(j-count)+48;
jaaaa, an diesem kleinen ding hing ich auch erst xD dann fiel es mir wie schuppen von den augen ^^
^^ Du siehst, man kommt offenbar auch ohne dein ganzes "Bromborium" aus. ;)
ich habs dir ja gesagt, das es für das bsp freilich auch ohne all das geht. aber ich habs eben gern, dass er möglichst allgemeingültig arbeitet. und das geht bei mehrstelligen zahlen (>10) nunmal nich, so wies hier is.

zur verdeutlichung: wenn du ne 4 speichern willst, schreibt er den ascii-code für die 4: 4+48 = 52. schau ich jetz in die ascii tabelle bei der 52, seh ich? gut, die 4 ^^ passt soweit. nu willste aber ne 12 speichern zum bsp. was passiert dann? er schreibt die 12+48 = 60. aus der 12 wird also ein < ;) sicher nich grad das, was du da stehen haben willst. man darf hier also keine 12 schreiben, sondern muss ne 1 UND ne 2 einzeln schreiben. und DAFÜR is das ganze "bromborium" da bei mir ^^

aber wie gesagt: für das bsp langt die einfache variante völlig aus :)
 
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

^^ Jo ... :)

Die Decodierfunktion zu basteln war ja ein Klacks und auch die Berücksichtigung von Groß- und Kleinschreibung habe ich schon drinnen. Ich hänge jetzt nur mehr beim neuerlichen Überschreiben des codierten Strings mit dem Originalstring:
Code:
#include <stdio.h>

int checkLength(char *s) {
    int length=0;

    while (*(s+length)!='\0') {
        length++;
    }

    return length;
}

double encode_runlength(char *s) {
    int i=0, j=1, k=0, count=0, length=checkLength(s);
    double ratio=0.0;

    while (*(s+i) != '\0') {
        if (*(s+i)!=*(s+j)) { 
            if ((j-count)==1) { 
                printf("%c", *(s+i));
                *(s+k)=*(s+i);
                k++; 
                count=j;
            } else { 
                printf("%c%d", *(s+i), (j-count));
                *(s+k)=*(s+i); 
                *(s+k+1)=(char)(j-count)+48; 
                k+=2; 
                count=j;
                ratio=(double)k; 
                *(s+(int)ratio)='\0'; 
            }            
        }
        i++;
        j++;
    }

    return ((ratio*100)/(double)length);
}
[COLOR=royalblue][B]
int decode_runlength(char *s) {
    int i=0, j=0, k=0, count=0, length=0;

    while (*(s+i)!='\0') {
        if (*(s+i+1)>=50 && *(s+i+1)<=57) { 
            count=(*(s+i+1)-48); 
            for (j=0; j<count; j++) {
                printf("%c", *(s+i));
            }
            i+=2;
            length+=count;
        } else { 
            printf("%c", *(s+i));
            i++;
            length++;
        }
    }


    *(s+length)='\0';

    printf("\n\nlength = %d\n", length);
    printf("s      = %s", s);

    return 0;
}[/B]
int main(void) {
    char s[] = "AAAABBBCCCCCCCCDEABBBBDDDDDDDD";
    int i=0;

    while (*(s+i)!='\0') {
        if (*(s+i)>=97 && *(s+i)<=122) {
            *(s+i)-=32;
        }
        i++;
    }

    printf("Original:   %s", s);
    printf("\nCodiert:    ");
    printf("\nVerk%crzung: %.0lf %%\n", 129, (100-encode_runlength(s)));
    printf("Decodiert:  ");
    decode_runlength(s);
    printf("\n\n");

    return 0;
}
Capture.JPG

Hilfe, bitte?!

Ein neues Ende könnte ich dem String ja recht simpel zuweisen:
Code:
*(s+length)='\0';
Aber die Elemente von 0 bis 29?! Da scheitert es noch ...
Mein Problem ist, ich wüsste schon, wie's zu machen wäre, aber nicht wo genau! Wenn ich das Ganze jetzt nämlich in die while Schleife dazu reinprogrammiere, so, wie wir's ja auch in encode_runlength() gemacht haben, verändere ich auch alles andere, das decode_runlength() macht.
 
Zuletzt bearbeitet:
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

Ich komme der Sache näher ...
Witzigerweise funktioniert das Überschreiben einigermaßen, wenn ich jetzt in *s von hinten damit anfange, versteh' einer, warum.

Ist aber noch ein bisschen eine "wackelige" Angelegenheit. 2 der 3 einzelnen Buchstaben mittendrinnen fehlen ihm noch + ein fehlendes B beim zweiten B-Vorkommen und dafür habe ich vorne 3 alte Zeichen, die noch nicht entsprechend überschrieben werden, weil er noch nicht bis soweit nach vorne im Feld kommt:

Capture.JPG

Code:
int decode_runlength(char *s) {
    int i=0, j=0, k=0, count=0, length=0;

  [COLOR=seagreen]  /* Ausgabe des decodierten Strings */    while (*(s+i)!='\0') {
        if (*(s+i+1)>=50 && *(s+i+1)<=57) { [COLOR=seagreen]/* Zahl erkannt: Buchstabe mehrmals vorhanden. */            count=(*(s+i+1)-48); [COLOR=seagreen]/* count = Anzahl des jeweiligen Buchstabens. */            for (j=0; j<count; j++) {
                printf("%c", *(s+i));
            }
            i+=2;
            length+=count;
        } else { [COLOR=seagreen]/* Einmal vorkommende Buchstaben. */            printf("%c", *(s+i));
            i++;
            length++;
        }
    }

    [COLOR=seagreen]/* Speicherung des decodierten Strings in *s */    [COLOR=royalblue][B]i=checkLength(s);
    count=0;
    *(s+length)='\0';
    while (i>0) {
        if (*(s+i)>=50 && *(s+i)<=57) {
            count=(*(s+i)-48);
            for (j=1; j<=count; j++) {
                *(s+(length-j))=*(s+(i-1));
            }
            length-=count;
        } else {
            *(s+length)=*(s+i);
        }
        i--;
    }[/B]
    printf("\n\ns = %s", s);

    return 0;
}
 
Zuletzt bearbeitet:
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

mein erster ansatz war, das ganze von hinten aufzurollen. also ich les das letzte zeichen: ne zahl. ne zahl heisst, dass vom nachfolgenden zeichen (also dem eigentlichen vorgänger) eben jene anzahl geschrieben werden muss. in unserm fall is das ne 8 und er liest das zeichen D. jetzt hätte ich "einfach" an das vorhandene D 8-1 D's angehängt. as A4B3C8DEAB3D8 wäre also schonmal A4B3C8DEAB3DDDDDDDD geworden.

danach würde er die 3 lesen (man muss natürlich mit den zeigereien aufpassen ^^) und dann das B. macht also aus
A4B3C8DEAB3DDDDDDDD
A4B3C8DEABBBDDDDDDD
überschreibt also ein D ^^ ungut. ergo müsste man das ende zuerst "weiterschieben". also als zwischenschritt ein
A4B3C8DEABB3DDDDDDDD
generieren. wo man jetz die kopiererei endet, is dann am ende geschmackssache. ich habs jetz gedanklich beim B enden lassen. man hat also das originale B dastehn und danach das nach hinten kopierte B3DD... hmm, mein zahlen schreiber in der encode funktion macht doch an sich schon das selbe *grübel* das könnte man hier vllt gleich verwenden. anschließend malt er hinters vorhandene (originale) B noch 2 weitere und wir haben:
A4B3C8DEAB3D8
A4B3C8DEAB3DD8 // der zwischenschritt würde hier ja auch kommen
A4B3C8DEAB3DDDDDDDD
A4B3C8DEABB3DDDDDDDD // wieder der zwischenschritt
A4B3C8DEABBBDDDDDDDD

usw usf. von vorne anfangen wäre unkuhl, weil man ja dann überschreibt, was man auswerten muss, daher der ansatz, von hinten zu beginnen. aber gut, von vorne her müsste man die weiterrückerei vom rest halt nur gescheit umgestalten *einfällt* ginge also wohl auch ^^ und is im endeffekt vllt sogar sinniger. das dekodierte (längere) bei jedem schritt zu verrücken, kostet mehr zeit (mehr zeichen zu verrücken), wie immer den codierten restschwanz zu verrücken. zumal das decodierte ja auch immer länger wird, und das codierte rest stück immer kürzer. hmm, also aus performancesicht wäre es sinnvoller, doch von vorne her zu decodieren und den rest nach hinten zu verschieben.

das einzige prob, das ich noch hab: wir haben ja jetzt unser definiertes s[]. auch wenn wir mittenrein ein '\0' schreiben und ned ans ende, so sollte der speicher für die restlichen zeichen ja dennoch belegt sein. eigentlich ^^ jetzt wäre es aber für die sinnvolle übung glaube besser, wenn man von reserviertem speicher bis zur neu gesetzten '\0' ausgeht. also wie wenn man beim encodieren die '\0' setzt und die restlichen zeichen per free() oder so freigibt. warum? naja, wenn man was codiertes aus ner externen quelle bekommt, dann is da auch nur der speicher fürs codierte reserviert.

nun hat man aber in dem fall das problem, dass man bei jedem decodierungsschritt speicher allocieren muss. nur wie das im einzelnen funzt, da hab ich keinen blassen :/ DAS wäre mein problem hierbei. wenn ich nen zeiger hab - eben sinnigerweise bei uns am ende - und hier speicher dazu baue, gilt das dann ab dem zeiger? also fügt er den speicherplatz dann hinten dran oder sagt er dann, dass s bei dem aktuellen zeiger beginnt und x-weit reserviert is?

ma als bsp versucht darzustellen:
Code:
s[] = [A][3][B][4][\0]
*(s + length) = (char) malloc(1); // aus A3 AAA machen heisst ein A hinzufügen
// is das nun so a):
s[] = [A][3][B][4][\0][NULL]
// oder so b):
s[] =             [NULL]

// müsste man zudem nich ganz und gar sowas schreiben:
*(s + length) = (char) malloc(1 * sizeof(char));
 
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

^^ Danke für die Schreibarbeit, hab's aber mittlerweile schon selbst rausgefunden (siehe mein voriges Posting) ... ;)

Muss nur noch den Fehler beseitigen. :)
von vorne anfangen wäre unkuhl, weil man ja dann überschreibt, was man auswerten muss, daher der ansatz, von hinten zu beginnen.
Ja, sowas habe ich mir schon gedacht. Da kommen sich wieder Lesen und Schreiben in die Quere.
 
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

das haste während meines schreibens gepostet gehabt ^^ und: du machst es scheinbar so, wie ichs anfänglich auch wollte - von hinten her. ich bin in dem letzten post von mir aber grad zu dem schluss gekommen, dass von vorne beginnen vllt sinnvoller wäre ^^ zudem steht die frage mit dem speicher zeug im raum :P
 
AW: [C] Hilfe beim Programmieren und Verständnis-Fragen zu Code-Beispielen ...

Ja ja, hatte ich schon zuvor gepostet und ich habe dein letztes Posting trotzdem gelesen. Sehe aber nicht den (performancetechnischen) Unterschied zwischen von hinten und von vorne anfangen. Man muss so oder so was verschieben?! Beim Ansatz von hinten, liest du aber früher/schneller die Zahlen, also minimal weniger Sucharbeit ...

Zu deiner Speicherfrage: Ich denke, dass man durchaus über die Nullterminierung hinausschreiben kann (bzw. die '\0' überschreiben kann --> das machen wir ja die ganze Zeit, oder?!) und für alles, was ich schreibe, muss Speicher allokiert werden. Die Nullterminierung ist meines Wissens nach nur was zum Lesen, wenn ich das String-Ende finden will.

[EDIT]
Ok, die mehrfachen Buchstaben habe ich jetzt alle erwischt, nur ich bekomme die einzelnen Buchstaben nicht rein:
Code:
i=checkLength(s);
    count=0;
    *(s+length)='\0';
    while (i>0) {
        if (*(s+i)>=50 && *(s+i)<=57) {
            count=(*(s+i)-48);
            for (j=1; j<=count; j++) {
                *(s+(length-j))=*(s+(i-1));
            }
            length-=count;
        } else {
            *(s+(length-1))=*(s+i);
        }
        i--;
    }
Ausgabe: *s = A4BAAAABBBCCCCCCCCBBBBDDDDDDDD

PS: Ich weiß, dass das length--; im else noch fehlt, aber wenn ich es einfach so reinschreibe --> Stack arround the variable 's' was corrupted. Da scheitert es wahrscheinlich an i und/oder length auch noch.
 
Zuletzt bearbeitet:
Zurück