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



## boss3D (10. August 2012)

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

Hi @ all!

Ich brauche für einen großen Code eine kleine Funktion, die mir Hochzahlen berechnet. Da ich lieber mit einzelnen "Bäumen" arbeite, als mit dem ganzen "Wald" auf einmal, versuche ich, diese kleine Funktion erst einmal unabhängig vom großen Code zu schreiben und erst, wenn sie funktioniert, zu implementieren. Die Funktion pow der Bibliothek math.h soll/darf dabei nicht verwendet werden ...

Eigentlich habe ich schon ein Bisschen Ahnung von C, aber irgendwie komme ich nicht dahinter, wieso mein kleiner Code nicht die gewünschten Ergebnisse liefert:


```
#include <stdio.h>

int exp(int a, int b) {
    int i=1;

    for (i; i<=b; i++) {
        a*=a;
    }

    return a;
}

int main(void) {
    int basis=0, exponent=0;

    printf("Please enter any value for basis: ");
    scanf("%d", &basis);
    printf("Please enter any value for exponent: ");
    scanf("%d", &exponent);
    printf("\n%d^%d = %d\n\n", basis, exponent, exp(basis, exponent));

    return 0;
}
```
Vielleicht sieht von euch wer den Fehler?!

Danke für baldige Antworten!


----------



## XT1024 (10. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Moin


```
#include <stdio.h>

int exp(int a, int b) {
    int i=1;
    [COLOR=red]int x=a;
    for (i; [COLOR=red]i<b; i++) {
        [COLOR=red]x=[COLOR=red]x*a;
    }

    return [COLOR=red]x;
}

int main(void) {
    int basis=0, exponent=0;

    printf("Please enter any value for basis: ");
    scanf("%d", &basis);
    printf("Please enter any value for exponent: ");
    scanf("%d", &exponent);
    printf("\n%d^%d = %d\n\n", basis, exponent, exp(basis, exponent));

    return 0;
}
```
Mit den roten Änderungen klappt das jedenfalls bei mir.


----------



## FreezerX (10. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Der Fehler liegt im a*=a. 

Das a verändert sich und bleibt nicht konstant.


----------



## fadade (10. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Hier eine aus meiner kleinen mathe-lib 


```
public static double exp(double k, int n)
            {
                double erg = 1.0d;

                if (n > 0)
                {
                    while (n-- > 0)
                    {
                        erg *= k;
                    }
                }
                else if (n < 0)
                {
                    erg = k;
                    while (n++ < 0)
                    {
                        erg *= 0.1d;
                    }
                }
                else if (n == 1)
                { return k; }

                return erg;
            }
```


----------



## boss3D (10. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*



FreezerX schrieb:


> Der Fehler liegt im a*=a.
> 
> Das a verändert sich und bleibt nicht konstant.


 Ok, was du meinst verstehe ich, aber wieso funktioniert dann die Lösung von XT1024, der ja nichts anderes macht, als x gleich a zu setzen? Ist das so zu verstehen, dass x den (Start-)Wert von a bekommt, aber an einer anderen Adresse im Speicher ablegt und ich dann den Wert zurückgebe, der an der Adresse von x liegt?

Und wieso i<b? Es soll ja bis zur gewünschten Hochzahl gerechnet werden und nicht schon eins vorher aufgehört werden. Wieso funktioniert das mit i<b, aber nicht mit i<=b?


----------



## Cinnayum (10. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Mal abgesehen davon, dass die die Definition von x^0 = 1 vergessen hast, steht der Fehler im 3. Posting.

Du rechnest bei 2^2

2 * 2 = 4

Bei 3^3 rechnest du im 1. Schleifendurchlauf

3 * 3 = 9 aber im 2. mit dem ERGEBNIS des 1. weiter:

9 * 9 = 81

Du musst dir die Basis in einer extra Variable festhalten. Außerdem glaube ich, dass deine Schleifenabbruchbedingung nicht stimmt. (Oh steht auch schon in rot da)


----------



## boss3D (10. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*



Cinnayum schrieb:


> dass die die Definition von x^0 = 1 vergessen hast


Stimmt. Aber der Fall kommt im großen Programm eh nicht vor. [Edit] Hab's jetzt trotzdem schnell so geändert, dass der Fall auch berücksichtigt würde. 
----------------------

Ich habe das jetzt in den großen Code implementiert, nur leider liefert dieser noch nicht ganz das gewünschte Ergebnis. Das muss allerdings nicht an der kleinen Hochzahlfunktion liegen! 

Es geht darum, folgende Ausgabe durch mehrere Berechnungen und geschickte Formatierung zu erreichen:




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



Die genäherten Werte sollen dabei über die Taylor-Reihe berechnet werden:




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



Meine Ausgabe kommt dem schon relativ nahe, aber stimmt noch nicht zu 100 % mit der Vorgabe überein:




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



Hier mein Code:


```
#include <stdio.h>
#include <math.h>

int fakultaet(int x) { /* Fakultät rekursiv */
    if (x == 0)
        return 1;
    else
        return (x * fakultaet(x-1));
}

int hochzahl(int a, int b) { /* Berechnung der Hochzahl; eingesetzt werden die Werte 'start' und 'hoch' aus Funktion exp_genaehert; start steht für x in der Taylorreihe */
    int i=1, j=a;
    
    if (b == 0) {
        return 1;
    } else {
        for (i; i<b; i++) {
            j*=a;
        }
    }
    
    return j;
}

double exp_exakt(int start) { /* Berechnung des exakten x */
    double exakt=0.0;

    exakt=exp(start);

    return exakt;
}

double exp_genaehert(int start, int end) { /* Berechnung des genäherten x durch die Taylorreihe */
    int j=0, hoch=0;
    double genaehert=1.0+start, i=0.0;

    for (hoch=2, j=2; hoch<=end, j<=end; hoch++, j++) { /* 'hoch' steht für Hochzahl; vom jeweiligen j soll in jedem Schleifendurchlauf die Fakultät berechnet werden */ 
        i=fakultaet(j); 
        genaehert += ((1/i)*(hochzahl(start, hoch))); /* Berechnung der Taylorreihe */ 
    }

    return genaehert;
}

int main(void) {
    int start=0, end=10, inc=2;
    double err_bound=0.0010000000;

    printf("Naeherungsweise Berechnung von exp(x)\n\n");
    printf("Startpunkt: %d\n", start);
    printf("Endpunkt: %d\n", end);
    printf("Schrittweite: %d\n", inc);
    printf("Fehlerschranke: %.10lf\n\n", err_bound);
    printf(" x : exp(x) genaehert : exp(x) exakt     : Fehler\n");
    printf("============================================================\n");
    for (start; start<=end; start+=inc) {
        printf("%2d : %16.10lf : %16.10lf : %.10e\n", start, exp_genaehert(start, end), exp_exakt(start), (exp_exakt(start)-exp_genaehert(start, end))); /* Ausgabe sämtlicher Ergebnisse der Funktionen für den jeweiligen Start-Wert */
    }
    putchar('\n');

    return 0;
}
```
Wodurch kommen die Abweichungen zustande? Irgendwie muss es wohl an meiner Berechnung der Taylor-Reihe liegen, aber ich finde den Fehler nicht ...


----------



## bingo88 (10. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Du kannst die TR auch einfacher berechnen:

1 + x*(1 + x/2 * (1 + x/3 * (... (1 + x/n))...))

Dann fängst du "von innen" an zu rechnen, also du fängst mit 1 + x/n an und arbeitest dich dann nach außen bis 1 + x vor. Damit sparst du dir schon mal die Fakultät und das Potenzieren.


----------



## nay (10. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*



fadade schrieb:


> Hier eine aus meiner kleinen mathe-lib
> 
> 
> ```
> ...


 
Was spuckt das Programm aus wenn du 2^(-1) hast oder 2^(-10)?

Dein Code funktioniert nur bei 10er Potenzen und 0.


----------



## joffal (10. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*



nay schrieb:


> Was spuckt das Programm aus wenn du 2^(-1) hast oder 2^(-10)?
> Dein Code funktioniert nur bei 10er Potenzen und 0.


 
Negative Potenzen sind ja eine Teilung durch 10, sprich 2^-1 ist dasselbe wie 2* (1 / 10^1)  und 2^-2 wären dann gleich 2 * ( 1 / 10^2) usw.
Und das steht soweit ich das erkenne auch in seinem Code:

```
else if (n < 0) {     erg = k;     while (n++ < 0)    {       erg *= 0.1d;    } }
```


@fadade: du hast das jetzt ja mit " *= " gelöst, warum keine Rekursion?


----------



## nay (10. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Dann lass mal den Code laufen. Wenn du 2^(1) einwirfst kommt 0.2 raus, was falsch ist.

-----

Eine rekursive Lösung wäre so:


```
double power(double x, int n)
{
    if (n>0)
        return x*power(x, n-1);

    else if (n==0)
        return 1;

    else
        return power(1/x, -n);
}
```


----------



## JimSim (10. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*



joffal schrieb:


> Negative Potenzen sind ja eine Teilung durch 10, sprich 2^-1 ist dasselbe wie 2* (1 / 10^1)  und 2^-2 wären dann gleich 2 * ( 1 / 10^2) usw.


 
Eh, nein. 2^-2 = 1/(2^2) bzw. x^-y = 1/(x^y)


----------



## joffal (10. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

@JimSim: alles klar dann halt so 
da muss fadade aber mal nachbessern (wenn er es für allgemeine zahlen haben möchte ...)

@nay: ich habe es jetzt nicht gemacht, aber wenn du 2^(1) haben möchtest, dann ist k=2 und n=1, sprich der Code spring hier rein:

```
if (n > 0) {     while (n-- > 0)      {         erg *= k;       }
```
dann verringert er n um ist (ist dann 0) und multipliziert erg (1.0) mit k(=2), dann ist in erg ne 2 drin und bei der nächsten prüfung der schleifenbedingung müsste er abbrechen und erg=2 zurückgeben --> 2^1 = 2


----------



## nay (10. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Ich meine doch 2 hoch *minus *1 

Da kommt man hier rein


```
else if (n < 0) {     erg = k;     while (n++ < 0)     {         erg *= 0.1d;     } }
```

und raus kommt 0.2. Es müsste 0.5 rauskommen.


----------



## fadade (10. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Ui ui ... jetz meld ich mich doch lieber nochmal, bevor hier ein Forenkrieg ausbricht 
Der Code den ich geposted habe war vorhin so schön weit oben und ich hab das Kommentar nicht gelesen, in welchem ich eindeutig vermerkt habe, dass der Code nur für einen bestimmten Zweck bei mir gedacht ist.

Hier mal die "normale" exp-Funktion. Hat einen kleinen und doch großen Unterschied (da kommt auch etwas Rekrusion mit rein joffal  )


```
public static double exp(double k, int n)
            {
                double erg = 1.0d; // für k^0 vorgespeicherter Wert

                if (n == 1)
                { 
                    return k; 
                }
                else if (n > 1)
                {
                    while (n-- > 0)
                    {
                        erg *= k;
                    }
                }
                else if (n < 0)
                {
                    erg = 1 / exp(k, n);
                }
                
                return erg;
            }
```


----------



## nay (11. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Es ist leider immer noch falsch  Es muss heißen:

```
...

else if (n < 0)
{
     erg = 1 / exp(k, [B]-[/B]n);
}

...
```
Also es muss ein Minus vor das n sonst wird sich der CPU Lüfter bemerkbar machen


----------



## fadade (11. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

oh tatsächlich!  
Zum Glück habe ich die Methode so in der Form noch gar nicht benutzt ...

Aber ist deine Frage wenigstens geklärt? ^^


----------



## nay (11. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Ich verstehe, dass du die Funktion in Post #4 für einen bestimmten Zweck geschrieben hast aber ich weiß nicht genau warum du das so verwirrend verpackt hast 
Mach doch eine Funktion posExp für Potenzen mit positivem Exponenten und eine andere Funktion eNeg, die das Komma einer Zahl nach links verschiebt.


----------



## boss3D (11. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Hier den Fehler, der zu den Abweichungen vom "erwarteten" Ergebnis führt, zu suchen, hat eh keiner Lust, oder?


----------



## bingo88 (11. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*



boss3D schrieb:


> Hier den Fehler, der zu den Abweichungen vom "erwarteten" Ergebnis führt, zu suchen, hat eh keiner Lust, oder?


 Hast du das mal mit der "vereinfachten" TR versucht, die ich vorgeschlagen habe? Ich hatte mal ein Programm geschrieben, das auch 50% Abweichung bei den Berechnungen hatte, nur weil ich "falsch" addiert hatte (sehr kleine auf sehr große Werte gibt nur große Wert -> Müll). Eventuell kannst du mit der vereinfachten Berechnung schon dein Problem lösen


----------



## nay (11. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Es gibt keinen Fehler alles was du machen musst ist eine Taylorreihe mit 10 Summanden. Die Genauigkeit in den Beispielen stimmt nicht überein.

btw du hast 11 Summanden aber das Ergebnis ist ist nicht falsch sondern sogar genauer als das erwartete Ergebnis.


----------



## boss3D (11. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*



bingo88 schrieb:


> Hast du das mal mit der "vereinfachten" TR versucht, die ich vorgeschlagen habe? Ich hatte mal ein Programm geschrieben, das auch 50% Abweichung bei den Berechnungen hatte, nur weil ich "falsch" addiert hatte (sehr kleine auf sehr große Werte gibt nur große Wert -> Müll). Eventuell kannst du mit der vereinfachten Berechnung schon dein Problem lösen


Sorry, aber deinen Lösungsweg kann ich leider gar nicht nachvollziehen. Fehlen dir nicht die ganzen Hochzahlberechnungen? Ich finde da meinen Weg (obgleich länger) verständlicher, aber ist sicher Ansichtssache.


nay schrieb:


> Es gibt keinen Fehler alles was du machen musst ist  eine Taylorreihe mit 10 Summanden. Die Genauigkeit in den Beispielen  stimmt nicht überein.
> 
> btw du hast 11 Summanden aber das Ergebnis ist ist nicht falsch sondern sogar genauer als das erwartete Ergebnis.


Oha!  

Auf das hätte ich echt selber kommen können, dass ich einfach nur über's Ziel hinausgeschossen bin ... und dabei suche ich schon seit 3 Tagen den "Fehler". 

Ich habe jetzt die Funktion _exp_genaehert_ mal entsprechend geändert (10 Summanden):

```
double exp_genaehert(int start, int end) {
    int j=0, hoch=0;
    double genaehert=1.0+start, i=0.0;

    for (hoch=2, j=2; hoch<end, j<end; hoch++, j++) {  
        i=fakultaet(j); 
        genaehert += ((1/i)*(hochzahl(start, hoch)));
    }

    return genaehert;
}
```
Ich weiß, dass es 100 %ig identisch geht und das will ich noch hinkriegen. Trotzdem schon mal danke für's Augenöffnen!  

[Edit]
Mit 10 Summanden bin ich wieder weiter weg vom "Zielergebnis", dabei sollte es gerade mit 10 hinkommen?! 10 = end.


----------



## bingo88 (11. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Ein Beispiel:

e^x mit x = 4, n = 4

Klassisch: 1 + 4 + 4^2/2! + 4^3/3! + 4^4/4! = 103/3

Vereinfacht: 1 + 4 * (1 + 4/2 * (1 + 4/3 * (1 + 4/4))) = 103/3

Für den "richtigen" Wert von e^4 fehlen aber noch ein paar Iterationen


----------



## nay (11. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Du musst für e^6, e^8 und e^10 die Anzahl der Summanden anpassen und gleichzeitig einige Datentypen ändern.
*int* kann so große Zahlen wie 10^30 z.B. nicht halten.

Eigentlich macht man die Taylorreihe so lang bis sich die an der gewünschten Genaugkeit nichts mehr geändert hat.


----------



## boss3D (11. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*



nay schrieb:


> Du musst für e^6, e^8 und e^10 die Anzahl der Summanden anpassen und gleichzeitig einige Datentypen ändern.
> *int* kann so große Zahlen wie 10^30 z.B. nicht halten.


Das größte, was ich erreiche, wäre 10^10 (= 10000000000). Wenn ich allerdings den Funktionstyp jener Funktion, die die Hochzahlen berechnet, von *int* auf *long* ändere, ändert sich im Gesamtergebnis gar nichts. Ändere ich den Funktionstyp auf *double*, bekomme ich zwar andere Werte im Gesamtergebnis, die auch noch näher am gewünschten Ergebnis liegen, aber ich will nicht *double* verwenden, wenn es gar nicht um Kommazahlen geht ...

Wieso zeigt *long* hier keine Wirkung?

long:

```
long hochzahl(int a, int b) {
    long i=1, j=a;
    
    for (i; i<b; i++) {
        j*=a;
    }
    
    return j;
}
```



			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



double:

```
double hochzahl(int a, int b) {
    double i=1.0, j=a;
    
    for (i; i<b; i++) {
        j*=a;
    }
    
    return j;
}
```



			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.


----------



## bingo88 (11. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

ein long ist hier ein int, das stammt noch aus alten Zeiten 
Versuche es mal mit long long, der sollte 64 bit groß sein.

Hier mal mein Code zu der vereinfachten Variante. Bei e^x mit x=10 und 40 iterationen liefert der mir 22026.465795.


```
double my_exp(double x, int n)
{
    double res = 1.0;
    double sub = 1.0;
    int i;

    for (i = 1; i < n; ++i)
    {
        sub *= x/i;
        res += sub;
    }

    return res;
}
```


----------



## nay (11. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Ja die Potenzfunktion sollte eigentlich double zurückgeben, ist bei mir auch performanter als die Funktion in Post #26 mit int Typen.

Die Fakultät Funktion sollte ein unsigned int64 (oder wenigstens ein unsigned int) zurückgeben. Eine Möglichkeit das zu machen ist


```
typedef unsigned long long uint64;
printf("sizeof(uint64) returns %d Byte\n\n", sizeof(uint64)); // zum Testen
```


----------



## boss3D (11. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

*long long* als Funktionstyp bei der Potenzfunktion liefert das selbe, wie *double*. Scheint sich vom Wertebereich her also beides auszugehen. Wenn aber nay meint, dass *double* perfomanter sei, dann glaube ich das jetzt einfach mal und lasse es so.

BTW: Wieso *unsigned int* bei der Fakultätsfunktion? Das ändert genau gar nichts am Ergebnis?!


----------



## JimSim (11. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Naja, bei der Fakultätsfunktion haste eh nur positive Werte. (Negative Fakultät ist nicht definiert) Dann kann man sich auch den negativen Wertebereich der Variablen auch sparen und den positiven effektiv verdoppeln in dem man sie als unsigned definiert...


----------



## nay (11. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Naja ich hab es einfach ganz oft durchlaufen lassen und double war schneller als int. Außerdem gibt es auch Sachen wie e^1.5 oder so. 

Fakultäten gibt es nur für positive Integers also würde ich einfach unsigned nehmen, weil du sonst den Fehler abfangen müsstest. (in dem Fall egal, aber warum nicht gleich robusten Code schreiben?)

Edit: Eine Sache habe ich nicht verstanden: Warum soll deine selbst geschriebene Funktion ungenauer sein als die exp Funktion? Wenn dann ist es anders herum. Kannst du vielleicht sagen was die Aufgabe war? Würde mich interessieren.


----------



## boss3D (12. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*



nay schrieb:


> Außerdem gibt es auch Sachen wie e^1.5 oder so.


Ja, aber nicht in meinem konkreten Beispiel. Sonst wäre ich eh selber auf float oder double gekommen. 


nay schrieb:


> Fakultäten gibt es nur für positive Integers also würde ich einfach unsigned nehmen, weil du sonst den Fehler abfangen müsstest. (in dem Fall egal, aber warum nicht gleich robusten Code schreiben?)


Ok, hast recht.


nay schrieb:


> Edit: Eine Sache habe ich nicht verstanden: *Warum soll deine selbst geschriebene Funktion ungenauer sein als die exp Funktion?* Wenn dann ist es anders herum. Kannst du vielleicht sagen was die Aufgabe war? Würde mich interessieren.


Laut Angabe nähert die selbstgeschriebene Funktion auf Basis der Taylor-Reihe sich dem exakten Ergebnis nur an, während exp() der math.h angeblich den exakten Wert bestimmt?! Ich bin davon ausgegangen, dass das stimmt?! ...

Die Aufgabe habe ich schon im ersten Posting zu diesem Beispiel kurz beschrieben, aber hier noch einmal komplett:



			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        


Und hier meine derzeitige Lösung:

```
#include <stdio.h>
#include <math.h>

unsigned int fakultaet(int x) {
    if (x == 0)
        return 1;
    else
        return (x * fakultaet(x-1));
}

double hochzahl(int a, int b) {
    double i=1.0, j=a;
    
    for (i; i<b; i++) {
        j*=a;
    }
    
    return j;
}

double exp_exakt(int start) {
    double exakt=0.0;

    exakt=exp(start);

    return exakt;
}

double exp_genaehert(int start, int end) {
    int j=0, hoch=0;
    double genaehert=1.0+start, i=0.0;

    for (hoch=2, j=2; hoch<=end, j<=end; hoch++, j++) {  
        i=fakultaet(j); 
        genaehert += ((1/i)*(hochzahl(start, hoch)));
    }

    return genaehert;
}

int main(void) {
    int start=0, end=10, inc=2;
    double err_bound=0.0010000000;

    printf("Naeherungsweise Berechnung von exp(x)\n\n");
    printf("Startpunkt: %d\n", start);
    printf("Endpunkt: %d\n", end);
    printf("Schrittweite: %d\n", inc);
    printf("Fehlerschranke: %.10lf\n\n", err_bound);
    printf(" x : exp(x) genaehert : exp(x) exakt     : Fehler\n");
    printf("============================================================\n");
    for (start; start<=end; start+=inc) {
        printf("%2d : %16.10lf : %16.10lf : %.10e\n", start, exp_genaehert(start, end), exp_exakt(start), (exp_exakt(start)-exp_genaehert(start, end)));
    }
    putchar('\n');

    return 0;
}
```
Was ich eben nicht verstehe: Ich weiß, dass es bei der Taylor-Reihe, also *exp(x) genaehert* in der Ausgabe, mit maximal x^10 möglich ist, das exakt selbe Ergebnis zu erhalten, wie in der Angabe, aber ich komme einfach nicht hin.


----------



## boss3D (12. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

^^ Wem die Taylor-Reihe schon zu langweilig geworden ist, der darf mir bitte gerne verraten, warum mein _Sieb des Eratosthenes_ alle Zahlen als Primzahlen erkennt und nicht nur die, die es wirklich sind ...  _*ganz lieb schau*_ 

```
#include <stdio.h>

/* Sieb des Eratosthenes */
int is_prime(unsigned int num) {
    int i=2, j=0, k=0;

    if (num==2) { /* 2 ist die kleinste Primzahl */
        return 1;
    } else if (num==1) { /* 1 soll nicht als Primzahl gewertet werden */
        return 0;
    }

    for (i; i<=10000; i++) { /* alle Zahlen von 2 bis 10000 werden überprüft */
        for (j=i; j<=10000; j+=i) { /* alle Vielfachen des Startwertes der jeweiligen Runde werden ermittelt ... */
            k=j; /* ... und in k gespeichert */
            if (num!=k) { /* Alle Werte, die noch nie in k gespeichert wurden, sind Primzahlen */
                return 1;
            }
        }
    }

    return 0;
}

int main(void) {
    unsigned int num, i=1, j=0;

    printf("Please enter any number to check whether it's a prime: ");
    scanf("%d", &num);
    if (is_prime(num)==1) {
        printf("%d is a prime!\n", num);
    } else {
        printf("Sorry, no prime.\n");
    }
    putchar('\n');

    while (i<=1000) { /* Ausgabe der ersten 1000 Primzahlen */
        if (is_prime(j)==1) {
            printf("%d", j);
            printf(", ", i < 1000 ? ", " : "");
            j++;
            i++;
        } else {
            j++;
        }
    }
    putchar('\n');
    
    return 0;
}
```
Danke im Voraus!


----------



## nay (12. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Eigentlich ist long long oder int64 (oder wie man es auch immer nennen will) zu klein für dein Programm.
Um auf den Wert von e^10 zu kommen (22026.4652523840) braucht man 32 Summanden in der Taylorreihe also hat man Zahlen wie 32! und 10^32 (*zu groß!*).

Deswegen würde ich _fakultaet_ so definieren (ist zwar unschön aber effektiv)  
	
	



```
double fakultaet(double x)
```
Du machst immer eine Taylorreihe mit 10 Summanden, das ist zu ungenau für große Exponenten wie du siehst. Die Beispielausgabe wurde auf eine andere Art erstellt, etwa so:


```
double exp_genaehert(int n, double exact, double prec)
{
    if (prec <= 0 || exact <= 0) return -1;

    double x = 1 + n;
    unsigned int i = 2;

    /* invariant: i ist die Anzahl der Summanden der Taylorreihe */
    do
    {
        x += hochzahl(n, i) / fakultaet(i);
        i = i + 1;
    }
    while ((exact - x) >= prec);

    /* Info */
    /*printf("%2d Summanden ", i);*/

    return x;
}
```
Hier ist dein Code, den ich ein wenig abgewandelt habe:


```
#include <stdio.h>
#include <math.h>

#define exp_exakt(val) exp(val) /* Platzhalter */

double fakultaet(double x) { /* Fakultät rekursiv */
    if (x == 0)
        return 1;
    else
        return (x * fakultaet(x-1));
}

double hochzahl(double a, int b) { /* Berechnung der Hochzahl; eingesetzt werden die Werte 'start' und 'hoch' aus Funktion exp_genaehert; start steht für x in der Taylorreihe */
    double i=1, j=a;

    if (b == 0) {
        return 1;
    } else {
        for (i; i<b; i++) {
            j*=a;
        }
    }

    return j;
}

double exp_genaehert(int n, double exact, double prec)
{
    if (prec <= 0 || exact <= 0) return -1;

    double x = 1 + n;
    unsigned int i = 2;

    /* invariant: i ist die Anzahl der Summanden der Taylorreihe */
    do
    {
        x += hochzahl(n, i) / fakultaet(i);
        i = i + 1;
    }
    while ((exact - x) >= prec);

    /* Info */
    /*printf("%2d Summanden ", i);*/

    return x;
}

int main(void) {

    int i=0, end=10, inc=2;
    const double prec = 1.0e-3;
    double exact, approx, errmargin;

    printf("Naeherungsweise Berechnung von exp(x)\n\n");
    printf("Startpunkt: %d\n", i);
    printf("Endpunkt: %d\n", end);
    printf("Schrittweite: %d\n", inc);
    printf("Fehlerschranke: %.10lf\n\n", prec);
    printf(" x : exp(x) genaehert : exp(x) exakt     : Fehler\n");
    printf("============================================================\n");

    for (i; i <= 10; i=i+inc) {
        exact = exp_exakt(i);
        approx = exp_genaehert(i, exact, prec);
        errmargin = exact - approx;

        printf("%2d : %16.10lf : %16.10lf : %.10e\n", i, approx, exact, errmargin);
    }

    return 0;
}
```
Deine Siebfunktion ist sehr komisch, du machst nicht das was in den Kommentaren steht.  Fang am besten mal von vorne an und verwende dabei eine Datenstruktur (ein array wäre schon mal gut) und  programmiere nah am  Beispiel.


----------



## boss3D (12. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*



nay schrieb:


> Um auf den Wert von e^10 zu kommen (22026.4652523840) braucht man 32 Summanden in der Taylorreihe also hat man Zahlen wie 32! und 10^32 (*zu groß!*).
> 
> Deswegen würde ich _fakultaet_ so definieren (ist zwar unschön aber effektiv)
> 
> ...


Ich merke gerade, dass ich bei dem Beispiel einen wesentlich Punkt übersehen haben! Ich habe zwar brav die Fehlerschranke (err_bound) definiert, aber nie verwendet! OMG!  

Die Berechnung der Taylor-Reihe soll so lange laufen, bis der Wert von _genaehert_ kleiner als die Fehlerschranke werden würde ... 

Habe den Code jetzt noch einmal entsprechend umgeschrieben (siehe do-while Schleife in Funktion _genaehert()_):

```
#include <stdio.h>
#include <math.h>

unsigned int fakultaet(int x) {
    if (x == 0)
        return 1;
    else
        return (x * fakultaet(x-1));
}

double hochzahl(int a, int b) {
    double i=1.0, j=a;
    
    for (i; i<b; i++) {
        j*=a;
    }
    
    return j;
}

double exp_exakt(int start) {
    double exakt=0.0;

    exakt=exp(start);

    return exakt;
}

[COLOR=royalblue]double exp_genaehert(int start, int end, double err_bound, double res) {
    int j=2, hoch=2;
    double genaehert=1.0+start, i=0.0;

    [B]do {  
        i=fakultaet(j); 
        genaehert += ((1/i)*(hochzahl(start, hoch)));
        hoch++;
        j++;
    } while ((res-genaehert)>err_bound);[/B]

    return genaehert;
}
int main(void) {
    int start=0, end=10, inc=2;
    double err_bound=0.0010000000, [COLOR=royalblue]res=0.0;

    printf("Naeherungsweise Berechnung von exp(x)\n\n");
    printf("Startpunkt: %d\n", start);
    printf("Endpunkt: %d\n", end);
    printf("Schrittweite: %d\n", inc);
    printf("Fehlerschranke: %.10lf\n\n", err_bound);
    printf(" x : exp(x) genaehert : exp(x) exakt     : Fehler\n");
    printf("============================================================\n");
    for (start; start<=end; start+=inc) {
        [COLOR=royalblue]res=(exp_exakt(start));        printf("%2d : %16.10lf : %16.10lf : %.10e\n", start, exp_genaehert(start, end, err_bound, [COLOR=royalblue]res), exp_exakt(start), (exp_exakt(start)-exp_genaehert(start, end, err_bound, [COLOR=royalblue]res)));
    }
    putchar('\n');

    return 0;
}
```
Meinen großen Denkfehler hätten wir damit endlich gefunden. Nur leider bin ich jetzt minimal über dem erwarteten Ergebnis (Why?) ...
-------------


nay schrieb:


> Deine Siebfunktion ist sehr komisch, du machst nicht  das was in den Kommentaren steht.  Fang am besten mal von vorne an und  verwende dabei eine Datenstruktur (ein array wäre schon mal gut) und   programmiere nah am   Beispiel.


Öhm, glaub' mir, ich hätte das ganze sofort mit einem array gelöst, wenn ich denn dürfte! 

Zu dem Zeitpunkt, als wir auf der FH dieses Bsp. mit den Primzahlen bekommen haben, "kannten" wir offiziell noch keine arrays und durften die daher auch nicht verwenden. Deswegen würde ich das auch jetzt gerne ohne lösen, so wie's eben von der Angabe verlangt wird. 

BTW: Dass das Programm einfach alle Zahlen bis 1000 ausgibt, ist mir schon aufgefallen (ich teste immer!). Die Frage ist: Wie ändern?

PS: Wikipedia war meine Vorlage. Deswegen verstehe ich nicht, was ich so anders mache, als ich mir das mit den Kommentaren gedacht habe.


----------



## JimSim (12. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Was dein Sieb betrifft...


```
int is_prime(unsigned int num) {
    int i=2, j=0, k=0;

    if (num==2) { /* 2 ist die kleinste Primzahl */
        return 1;
    } else if (num==1) { /* 1 soll nicht als Primzahl gewertet werden */
        return 0;
    }

    for (i; i<=10000; i++) { /* alle Zahlen von 2 bis 10000 werden überprüft */
        for (j=i; j<=10000; j+=i) { /* alle Vielfachen des Startwertes der jeweiligen Runde werden ermittelt ... */
            k=j; /* ... und in k gespeichert */
            if (num==k) { /* Ist der Wert gleich der Vielfachen eines anderen Wertes, ist sie keine Primzahl */
                return 0;
            }
        }
    }

    return 1;
}
```

So sollte es was werden... Wenn die gegebene Zahl = einem Vielfachen einer Zahl ist, ist sie keine Primzahl. Durchläuft dagegen die Primzahl die ganze Schleife, ohne das ein Vielfaches mit der gegebenen Zahl übereinstimmt, ist sie (wahrscheinlich) eine Primzahl


----------



## boss3D (12. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

^^ Hast du das mal ausprobiert?! Da kommen nur unsinnige Werte raus, die fast alle noch dazu größer als 10000 sind ...


----------



## JimSim (12. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*


```
int is_prime(unsigned int num) {
    int i=2, j=0, k=0;

    if (num==2) { /* 2 ist die kleinste Primzahl */
        return 1;
    } else if (num==1) { /* 1 soll nicht als Primzahl gewertet werden */
        return 0;
    }

    for (i; i<=10000; i++) { /* alle Zahlen von 2 bis 10000 werden überprüft */
        for (j=i; j<=10000; j+=i) { /* alle Vielfachen des Startwertes der jeweiligen Runde werden ermittelt ... */
            if(j!=i) {
                     k=j; /* ... und in k gespeichert */
                     if (num==k) { /* Ist der Wert gleich der Vielfachen eines anderen Wertes, ist sie keine Primzahl */
                             return 0;
                     }
            }
        }
    }

    return 1;
}
```

Mist, wenn man natürlich jede Zahl mit jeder vergleicht kann das nichts werden... so ists was. Jetzt musst du natürlich noch ne Abfrage machen, damit er keine höheren Zahlen als 10000 prüft.


----------



## boss3D (12. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

^^ Vielen Dank, jetzt funktioniert es wirklich!  

Zwei Sachen wären bei dem Beispiel noch zu klären:
1. Kannst du bitte meine Kommentare checken, nur damit ich sicher sein kann, dass ich den Effekt von (if (j!=i)) richtig verstanden habe?!
2. Warum wird auch nach der 1000sten Primzahl noch ein Beistrich ausgegeben, obwohl doch nach der 999sten (i<1000) Schluss damit sein sollte?

```
#include <stdio.h>

/* Sieb des Eratosthenes */
int is_prime(unsigned int num) {
    int i=2, j=0, k=0;

    if (num==2) { /* 2 ist die kleinste Primzahl */
        return 1;
    } else if (num==1) { /* 1 soll nicht als Primzahl gewertet werden */
        return 0;
    }

    for (i; i<=10000; i++) { /* alle Zahlen von 2 bis 10000 werden überprüft */
        for (j=i; j<=10000; j+=i) { /* alle Vielfachen des Startwertes der jeweiligen Runde werden ermittelt */
            [COLOR=royalblue]if (j!=i) { /* Immer wenn j ungleich i ist, handelt es sich um ein Vielfaches von j */                 k=j; /* Die Vielfachen werden in k gespeichert */
                if (num==k) { /* Alle Werte, die in k gespeichert wurden, sind keine Primzahlen */
                    return 0;
                }
            }
        }
    }

    return 1;
}

int main(void) {
    unsigned int num, i=1, j=2;

    printf("Please enter any number to check whether it's a prime: ");
    scanf("%d", &num);
    if (is_prime(num)==1) {
        printf("%d is a prime!\n", num);
    } else {
        printf("Sorry, no prime.\n");
    }
    putchar('\n');

    while (i<=1000) { /* Ausgabe der ersten 1000 Primzahlen */
        if (is_prime(j)==1) {
            printf("%d", j);
            [COLOR=royalblue]printf(", ", i < 1000 ? ", " : "");            j++;
            i++;
        } else {
            j++;
        }
    }
    putchar('\n');
    
    return 0;
}
```


----------



## nay (12. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Du kannst die äußere Schleife schon bei sqrt(num) beenden.

Beispiel:

num = 100

Wenn irgendeine Zahl kleiner num (z.B. 22) durch eine Primzahl größer der Quadratwurzel von num (z.B. 11) teilbar ist, dann ist die Zahl (22) auch ein Vielfaches einer Zahl kleiner der Quadratwurzel von num.
Also wurde die 22 schon vorher durch eine andere Primzahl abgedeckt. Deswegen ist die Betrachtung der Vielfachen von 11 überflüssig.

22 => 2
33 => 3
...
99 => 3

Hier wäre mein Code:


```
int is_prime_sieve(unsigned int num)
{
    if (num < 2) return 0;

    int tBorder = (int)(sqrt(num));

    int i=2, j;

    for (i; i <= tBorder; i=i+1)
    {
        for (j=i+i; j <= num; j=j+i) /* beginnend mit dem Vielfachen von i !! */
        {
            if (num == j) return 0;
        }
    }

    return 1;
}
```


----------



## Freddycbv (12. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*



nay schrieb:


> Du kannst die äußere Schleife schon bei sqrt(num) beenden.
> 
> Hier wäre mein Code:
> 
> ...



Ist die innerste for-Schleife nicht genau das selbe wie if(!num%i) return 0; ?
Meine Lösung für Primzahlen sah bisher nämlich immer so aus:

```
bool isPrime(int Zahl)
{
    if(Zahl < 2) return false;
    for(int i=2; i< Zahl/2 +1; i++)
    {
        if(!Zahl % i)
            return false;
    }
    return true;
}
```
 Aber das mit der Quadratwurzel ist interressant. Das wusste ich noch nicht...


----------



## nay (12. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Modulo ist hier schneller als der Sieb, vor allem bei großen Zahlen. Deine Code wäre eine c++ Lösung, wobei 
	
	



```
if(!Zahl % i)
```
 eigentlich überall falsch sein müsste, da ! eine höhere Prio hat als %.

P.S.
Bei der Lösung mit Modulo kannst du statt Zahl/2 auch floor(sqrt(Zahl)) als obere Grenze nehmen, aus den gleichen gründen wie oben erwähnt.


----------



## boss3D (13. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

@ nay
Anhand deiner Postings vermute ich, dass du schon einige Programmiererfahrungen und echt Ahnung von der Materie hast. Ich bin immer noch Anfänger in C und deswegen geht's mir in erster Linie darum, Codes zu schreiben, die ich verstehe und deren Verhalten ich nachvollziehen kann. Ich glaube dir sofort, dass deine Variante performanter ist, als das Sieb, aber mit meinem derzeitigen Primzahlen-Code bin ich ganz zufrieden. Er erfüllt die Aufgabenstellung und ich verstehe, was er macht. 

Vielen Dank an alle für die Tipps! 
Werde noch einiges programmieren in den Ferien und wenn ich wieder wo anstehe, melde ich mich wieder ...


----------



## boss3D (15. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

So, neuer Code und 2 Fragen dazu ... 

Folgendes Programm soll überprüfen, ob gegebene Wörter Palindrome sind:

```
#include <stdio.h>

int checkLength(char word[]) {
    int length=0;

    while (word[length] != '\0') {
        length++;
    }

    return length;
}

int checkPalindrome(char word[]) {
    int i=0, length=checkLength(word); 

    for (i=0; i<=(length-1); i++) {
       [COLOR=royalblue] if (word[i] != word[((length-1)-i)]) {             if ((word[i]+32 != word[((length-1)-i)]) && (word[i]-32 != word[((length-1)-i)])) { 
                return 0;
            }
        }
    }

    return 1;
}

int main(void) {
    char word1[] = "Retsinakanister"; /* yes */
    char word2[] = "Saippuakivikauppias"; /* yes */
    char word3[] = "testwort"; /* no */
    char word4[] = "Lagerregal"; /* yes */
    char word5[] = "Smartphone"; /* no */
    char word6[] = "programmieren"; /* no */

    [COLOR=royalblue]if (checkPalindrome(word1)==1) {
        printf("%s is a Palindrome!\n", word1);
    } else {
        printf("Sorry, %s is no Palindrome.\n", word1);
    }
    if (checkPalindrome(word2)==1) {
        printf("%s is a Palindrome!\n", word2);
    } else {
        printf("Sorry, %s is no Palindrome.\n", word2);
    }
    if (checkPalindrome(word3)==1) {
        printf("%s is a Palindrome!\n", word3);
    } else {
        printf("Sorry, %s is no Palindrome.\n", word3);
    }
    if (checkPalindrome(word4)==1) {
        printf("%s is a Palindrome!\n", word4);
    } else {
        printf("Sorry, %s is no Palindrome.\n", word4);
    }
    if (checkPalindrome(word5)==1) {
        printf("%s is a Palindrome!\n", word5);
    } else {
        printf("Sorry, %s is no Palindrome.\n", word5);
    }
    if (checkPalindrome(word6)==1) {
        printf("%s is a Palindrome!\n", word6);
    } else {
        printf("Sorry, %s is no Palindrome.\n", word6);
    }    putchar('\n');

    return 0;
}
```
Das ganze funktioniert auch wunderbar, ABER ...

1. Warum funktioniert das Programm nicht mehr, wenn ich die erste if-Zeile in der for-Schleife lösche? Was die macht, sollte doch auch in der zweiten if-Zeile überprüft werden?!
2. Gibt es eine elegantere Lösung, als in der main 6 Mal dieses if-else Konstrukt zu schreiben? Irgendeine Schleifenlösung mit nur einer if-else Abfrage?


----------



## nay (15. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Kannst du mal erklären was du damit bezwecken willst?



> ```
> if ((word[i]+32 != word[((length-1)-i)]) && (word[i]-32 != word[((length-1)-i)]))
> ```



Du kannst mehrere strings in einem array zusammenfassen und dann per Schleife durchlaufen


```
char* string_arr[] = {"abc", "acb" ,"bac", "bca", "cab", "cba"/*,NULL*/};
```


----------



## boss3D (15. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*



nay schrieb:


> Kannst du mal erklären was du damit bezwecken willst?


Die Angabe verlangt, dass das Programm keinen Unterschied zwischen Groß- und Kleinschreibung machen soll. Die von dir zitierte Zeile soll eben bezwecken, dass zum Beispiel "ABCDdcba" als Palindrom erkannt wird. 
Mir wurde gesagt, dass die erste if-Zeile in der for-Schleife umsonst sei, weil die zweite if-Zeile deren Funktion bereits inkludiert?! Nur das Programm geht eben nur, wenn beide Zeilen da sind; deswegen frage ich mich, was stimmt ...

Wegen alternativen Ausgabe-Lösungen: Ich wäre jetzt noch auf das hier gekommen, nur ob's eleganter ist ... 

```
printf("%s\"%s\" %s\n", ((checkPalindrome(word1)==1) ? "" : "Sorry, "), word1, ((checkPalindrome(word1)==1) ? "is a Palindrom!" : "is no Palindrom."));
printf("%s\"%s\" %s\n", ((checkPalindrome(word2)==1) ? "" : "Sorry, "), word2, ((checkPalindrome(word2)==1) ? "is a Palindrom!" : "is no Palindrom."));
printf("%s\"%s\" %s\n", ((checkPalindrome(word3)==1) ? "" : "Sorry, "), word3, ((checkPalindrome(word3)==1) ? "is a Palindrom!" : "is no Palindrom."));
printf("%s\"%s\" %s\n", ((checkPalindrome(word4)==1) ? "" : "Sorry, "), word4, ((checkPalindrome(word4)==1) ? "is a Palindrom!" : "is no Palindrom."));
printf("%s\"%s\" %s\n", ((checkPalindrome(word5)==1) ? "" : "Sorry, "), word5, ((checkPalindrome(word5)==1) ? "is a Palindrom!" : "is no Palindrom."));
printf("%s\"%s\" %s\n", ((checkPalindrome(word6)==1) ? "" : "Sorry, "), word6, ((checkPalindrome(word6)==1) ? "is a Palindrom!" : "is no Palindrom."));
```
Danke für den Tipp mit dem char-array. Ich wusste doch, da gab's noch was. Ich hatte das sogar schon mal so programmiert gehabt, aber konnte mich nicht mehr erinnern. Habe mich in den letzten Monaten eher mit Java beschäftigt.


----------



## JimSim (15. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*


```
if (word[i] != word[((length-1)-i)]) { 
            if ((word[i]+32 != word[((length-1)-i)]) && (word[i]-32 != word[((length-1)-i)])) { 
                return 0;
            }
        }
```

Naja, gucken wir mal was hier passiert:
1. If-Anweisung: ist der Buchstabe in der linken Seite + x ein anderer als der Buchstabe von der rechten Seite - x?
2. If-Anweisung: ist der Buchstabe vielleicht links Großgeschrieben und rechts Kleingeschrieben? Oder umgekehrt?

Mit der ersten Anweisung stellen wir erstmal fest ob die Buchstaben überhaupt unterschiedlich sind. Sonst lässt er nämlich beispielsweise bei Anna bei der Überprüfung das 'nn' in die zweite If-Anweisung. Und was macht die? Ohne die erste Abfrage überprüft die zweite if-Abfrage nur, ob es ein 'Nn' oder 'nN' ist, nicht ob es vielleicht ein 'nn' oder 'NN' ist. Und da es eben nicht 'Nn' oder 'nN' ist, wird es durch gelassen und hier return 0; zurückgegeben. 'Anna' wäre also ohne die erste If-Abfrage kein Palindrom. 'AnNa' allerdings schon.


----------



## nay (15. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Zuerst würde ich bei Funktionen, denen du einen Zeiger übergibst immer ein _*const*_ vor den Parameter schreiben, falls du die hinterlegte Variable nicht ändern willst (= good practice).
Also bei checkLength und checkPalindrome.

Die erste if Abfrage ist zwingend notwendig, um herauszufinden ob die characters exakt gleich sind, denn das deckt die zweite if Abfrage nicht ab.


----------



## boss3D (15. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

^^ Genau meine Logik, was ihr beide beschreibt! Hätte mich gewundert, wenn ich da was "umsonst" reinprogrammiert hätte ...

@ nay
Jetzt kommen wir wieder zu meiner Schwäche, Zeigern. Wie war das? Wenn ein Feld als Funktionsparameter angegeben wird, dann wird eigentlich ein Zeiger auf das erste Feldelement übergeben?! Call by reference, quasi?! Ich wüsste nicht, was du in meinem derzeitigen Code sonst mit Zeigern meinst; habe ja sonst noch keine gemacht. 

Soll das also heißen ...

```
[COLOR=royalblue][B]const[/B] int checkLength(char word[])[COLOR=black] { 
... 
}  [COLOR=royalblue][B]

const[/B] int checkPalindrome(char word[])[COLOR=black] { 
... 
}
```
...?

[EDIT]
@ nay
So, das hier ist vermutlich die Lösung, die du dir gedacht hättest:

```
int main(void) {
    int i=0;
    char *word[] = {"Retsinakanister", "Saippuakivikauppias", "testwort", "Lagerregal", "Smartphone", "programmieren"};

    while (*(word+i) != '\0') {
        if (checkPalindrome(*(word+i))==1) {
            printf("\"%s\" is a Palindrome!\n", *(word+i));
        } else {
            printf("Sorry, \"%s\" is no Palindrome.\n", *(word+i));
        }
        i++;
    }

    return 0;
}
```
Es wird zwar nach dem Debuggen das Richtige angezeigt, nur leider kommt auch sofort eine Fehlermeldung:



			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



Und ich mit meinem beschränkten Zeigerverständnis sehe leider die Fehlerquelle im Code nicht ...


----------



## nay (15. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Du übergibst eigentlich einen Zeiger und kein ganzes Array. Ob du jetzt _*char word[]*_ oder _*char* word*_ schreibst ist egal. Da du einen Zeiger übergibst kannst du theoretisch auch die hinterlegte Variable ändern da du sowohl read als auch write Erlaubnis hast.

Mit dem Wort _*const *_versprichst du, dass du die hinterlegte Variable (den string) nicht änderst. Anders herum: Wenn du das Wort _*const *_weglässt geht man davon aus, dass du die hinterlegte Variable ändern möchtest.
Es hilft beim Lesen des Codes.


```
int checkLength(const char word[]) { ... }
int checkPalindrome(const char word[]) { ... }
```
-------

Dein Code kann so nicht funktionieren, da dein Array _*word*_ kein '\0' enthält.

Du kannst das so machen:


```
int main(void) {
    int i=0;
    char *word[] = {"Retsinakanister", "Saippuakivikauppias", "testwort", "Lagerregal", "Smartphone", "programmieren", NULL};

    while (*(word+i)) {
        if (checkPalindrome(*(word+i))==1) {
            printf("\"%s\" is a Palindrome!\n", *(word+i));
        } else {
            printf("Sorry, \"%s\" is no Palindrome.\n", *(word+i));
        }
        i++;
    }

    return 0;
}
```


----------



## boss3D (15. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Ah, ok ...

Hier jetzt das ganze Programm mit Zeigern:

```
int checkLength(const char *word) {
    int length=0;

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

    return length;
}

int checkPalindrome(const char *word) {
    int i=0, length=checkLength(word); 

    for (i=0; i<=(length-1); i++) {
        if (*(word+i) != *(word+(length-1)-i)) { 
            if ((*(word+i)+32 != *(word+(length-1)-i)) && (*(word+i)-32 != *(word+(length-1)-i))) { 
                return 0;
            }
        }
    }

    return 1;
}

int main(void) {
    int i=0;
    char *word[] = {"Retsinakanister", "Saippuakivikauppias", "testwort", "Lagerregal", "Smartphone", "programmieren", NULL};

    [COLOR=royalblue]while (*(word+i) != '\0') {        if (checkPalindrome(*(word+i))==1) {
            printf("\"%s\" is a Palindrome!\n", *(word+i));
        } else {
            printf("Sorry, \"%s\" is no Palindrome.\n", *(word+i));
        }
        i++;
    }

    return 0;
}
```
Wieso funktioniert bei dir folgende Zeile?

```
while (*(word+i)) {
```
Ist der Abgleich, ob die Nullterminierung schon erreich wird (siehe blaue Zeile in meinem Code), hier nicht zwingend notwendig?
BTW: Liege ich richtig in der Annahme, dass NULL und '\0' die selbe semantische Bedeutung haben?


----------



## nay (15. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Kurz zum Verständnis: Das Array _*word*_ ist nicht wie eine Zeichenkette standardmäßig null-terminiert und ist nicht das gleiche wie char[]! Es enthält Zeiger, die auf den ersten Character von Zeichenketten zeigen.

In deinem Beispiel zeigt 

(word + 0) auf 'R' /*etsinakanister\0*/
(word + 1) auf 'S' /*aippuakivikauppias\0*/
(word + 2) auf 't' /*estwort\0*/
usw.

Ich habe versucht durch NULL kenntlich zu machen, dass das Array dort aufhört. Statt NULL würde ich 0 schreiben (ich glaube das ist für alle Compiler verständlich) wodurch auf jeden Fall ein null-pointer erzeugt wird, der bei einer Wahrheitsprüfung ein _*false *_erzeugt.

Du kannst auch auf andere Möglichkeit rausfinden wann das Array aufhört aber ich finde diese Art mit einem null-pointer als letztem Element ziemlich einfach, weil du den Code praktisch schon dafür geschrieben hast.

'\0' und NULL haben nicht die gleiche Bedeutung. Aber dazu kannst du auch googlen, da findest du gute Erklärungen.


----------



## boss3D (16. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Ok, vielen Dank! Jetzt ist einiges klarer ...


----------



## boss3D (17. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Neue Aufgabe, falls noch wer Lust hat ... 

Es soll ein Code geschrieben werden, der für einen char-String char *s eine Lauflängencodierung durchführt. Das Ganze soll ausschließlich mit Zeigerarithmetik gemacht werden und die beiden Funktionen für's Encodieren und Decodieren müssen genau so aussehen (Rückgabetyp, Funktionsname, Parameter), wie im nachfolgenden Code. Zusätzliche Funktionen dürfen, wenn nötig, erstellt werden. Das codierte Ergebnis soll ebenfalls in char *s gespeichert werde, damit kein zusätzlicher String benötigt wird.

In der finalen Version soll die Zeichenkette an die main-Funktion übergeben werden (siehe auskommentierten Code), aber um mir beim Programmieren leichter zu tun, habe ich sie erst einmal in der main definiert. 

```
[COLOR=black]#include [COLOR=black]<stdio.h>
double checkLength(char *s) {
    int i=0;
    double length=0.0;

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

    return length;
}

double encode_runlength(char *s) {
    int i=0, j=0;
    double length=checkLength(s), count=1.0;

    for (j; j<=length; j++) { [COLOR=royalblue]/* Duchlaufe den ganzen String */        if (*(s+i+1)==*(s+i)) { [COLOR=royalblue]/* Wenn ein Feldinhalt identisch mit seinem Vorgänger ist, ... */            i++; [COLOR=royalblue]/* ... erhöhe i (und prüfe dank der Schleife wieder) */            count+=i; [COLOR=royalblue]/* Die Anzahl der Erhöhungen von i ist die Anzahl der selben Buchstaben hintereinander und soll in count gespeichert werden */        }
    }

    return count;
}

double decode_runlength(char *s) {

}

[COLOR=seagreen]/*int main(int argc, char *argv[]) {*/int main(void) {
    int i=0;
[COLOR=seagreen]
    /* 
    char *s = argv[1];

    [COLOR=seagreen]for (i; i<=(argc-1); i++) {
        printf("%s (%d Zeichen)\n", argv[i], i);
    } 
    */
    char *s = "AAAABBBCCCCCCCCDEABBBBDDDDDDDD";

    printf("%s (%d Zeichen)\n", s, ((int)checkLength(s)+1));
    printf("%d%c\n", (int)encode_runlength(s), *s);

    return 0;
}
```
Ich weiß, dass die Funktion zum Encodieren ATM noch nichts wirklich sinnvolles macht, aber mein erstes Ziel war einfach mal nur, es zu schaffen, dass die Ausgabe für den ersten Buchstaben und die Anzahl seiner Vorkommnisse hintereinander stimmt. Wenn das fehlerfrei läuft, überlege ich weiter. 

So, nur die Ausgabe ist leider 7A, statt 4A und ich komme nicht darauf, warum ...


----------



## bingo88 (18. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

*(s + i) kann man auch einfacher schreiben: s_

Deine Funktion checkLength gibt es auch schon: strlen (dazu #include <string.h> einfügen)

Zu dem Fehler: Du musst auch um count weiterspringen, wenn sich die Buchstaben unterscheiden. Damit überspringst du dann alle gleichen Buchstaben, die du zuvor schon betrachtet hast. Sonst würdest du ja bei AAAAB einfach mit dem nächsten A weitermachen.


		Code:
	

int count;
int len = strlen(s);

for (int i = 0; i < len; i += count)
{
    count = 1; // mindestens 1x haben wir ja schon (akt. betrachteter Buchstabe)

    // vergleiche akt. Buchstaben mit allen nachfolgenden (daher i+1)
    for (int j = i + 1; j < len; ++j)
    {
        if (s[i] == s[j])
            ++count; // Zähler erhöhen
        else
           break; // anderer Buchstabe -> Schleife abbrechen
    }

    printf("%d%c\n", count, s[i]); // gibt Anzahl + akt. Buchstaben aus
}


Noch was: Bei C-Programmen beginnen die Argumente in argv meist bei Index 1 und nicht 0. An Index 0 steht in der Regel der Programmpfad._


----------



## boss3D (18. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Dass *(s+i) gleichbedeutend mit s_ ist, weiß ich, aber wie gesagt: Es darf ausschließlich Zeigerarithmetik verwendet werden. Übrigens dürfen KEINE Funktionen der Bibliothek <string.h> verwendet werden. Habe ich oben vergessen zu erwähnen, sorry.

Mit deinem letzten Satz meinst du wohl, dass ich das i (Startwert) in der auskommentierten for-Schleife auf 1 setzen sollte?!

Danke für den Code. Werde das jetzt mal ausprobieren und mich da reindenken. _


----------



## bingo88 (18. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*



boss3D schrieb:


> Mit deinem letzten Satz meinst du wohl, dass ich das i (Startwert) in der auskommentierten for-Schleife auf 1 setzen sollte?!


 Ja genau. argv[1] ist in der Regel das erste vom Benutzer übergebene Argument.


----------



## boss3D (18. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

So, nach einer kleinen Optimierung der Funktion checkLength und dem Implementieren deines Codes komme ich jetzt auf 8A ... das wird immer kurioser. 

```
#include <stdio.h>

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

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

    return length;
}

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

    [COLOR=royalblue]for (i; [B]i<length[/B]; i+=count) {
        [B]count=1;[/B]
        for (j=i+1; [B]j<length[/B]; ++j) {
            if (*(s+i) == *(s+j)) {
                ++count;
            } else {
                break;
            }
        }
    }    return count;
}

double decode_runlength(char *s) {

}

/*int main(int argc, char *argv[]) {*/
int main(void) {
    int i=0;

    /* 
    char *s = argv[1];

    for (i=1; i<=(argc-1); i++) {
        printf("%s (%d Zeichen)\n", argv[i], i);
    } 
    */

    char *s = "AAAABBBCCCCCCCCDEABBBBDDDDDDDD";

    printf("%s (%d Zeichen)\n", s, ((int)checkLength(s)));
    printf("%d%c\n", (int)encode_runlength(s), *s);

    return 0;
}
```
Irgendwie verwirrt mich auch das fett markierte count=1 in der ersten for-Schleife. Vor dieser Schleife ist count in deinem Code undefiniert (ich habe es jetzt selbst mit 0 definiert), weswegen die Schleife meiner Ansicht nach gar nicht funktionieren dürfte. Dass count einen Startwert von 1 haben muss, kann ich nachvollziehen, aber wieso dann nicht gleich bei der Variablendeklaration definieren (int count = 1) und dafür zwischen den for-Schleifen weglassen?

Und wieso eigentlich i<length bzw. j<length als Endbedingung in den Schleifen? Warum nicht i<=length bzw. j<=length? length inkludiert ja die Nullterminierung eh nicht mehr, oder? Warum also noch einmal eins früher aufhören?


----------



## bingo88 (18. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Okay.

1) Was als int geht, kannst du auch als int machen (bspw. double als Textlänge bei checkLength)

2) Bei Schleifen die Zählvariable besser immer im Schleifenkopf initialisieren, das verhindert ungewollte Fehler.

```
for ([B]i = 0[/B]; i < len; ++i) // Bei C++ bzw. ab C99 geht auch for (int i = 0; i < len; ++i)
```
3) Erklärung der Schleife

```
// äußere Schleife für aktuell zu zählenden Buchstaben
// wenn die innere Schleife fertig ist, wird um count Buchstaben weitergesprungen,
// da es sich dabei um die gleichen Buchstaben handelt - die dürfen wir aber nicht
// noch einmal betrachten!
for (int i = 0; i < len; i += count)
{
    // der Counter beginnt für jeden zu zählenden Buchstaben bei 1, daher muss der hier
    // mit 1 jedesmal neu initialisiert werden
    count = 1;

    // innere Schleife: Zählt das Vorkommen des akt. betrachteten Buchstabens (starte bei i + 1, da wir den Startbuchstaben ja schon haben)
    for (int j = i + 1; j < len; ++j)
    {
        if (s[i] == s[j])
            ++count; // Zähler erhöhen
        else
            break; // anderer Buchstabe -> innere Schleife abbrechen
    }

    printf("%d%c\n", count, s[i]); // gibt Anzahl + akt. Buchstaben aus
}
```
4) Mein Code liefert übrigens bereits die komplette RLE für den String (das printf), nicht nur für die ersten vier Buchstaben. Daher dürfte der Rückgabewert in deinem geposteten Code auch nicht unbedingt das erwartete Ergebnis enthalten (also bei dir gibt der 8 für die D's aus weil das der letzte Wert ist).

5) Length = Anzahl Elemente, Text ist in str[0] bis str[length-1] enthalten. Wenn du mit i <= length arbeitest, liest du noch das Nullzeichen mit ein. Bei nicht-nullterminierten Strings schmiert dir dann das Programm mit nem Fehler ab (Speicherschutzverletzung oder ähnliches)


----------



## DarkMo (18. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

bei aabccca müsste der dann doch sowas wie

2a
1b
3c
1a

ausgeben oder? sollte er aber nich geschickterweise

3a
1b
3c

ausgeben? ^^ oder is das nich ganz so relevant hierbei? für das 2. müsste man für jeden buchstaben den kompletten (rest)string abwandern und irgendwie vermerken, welche buchstaben man schon hatte *denk* vllt nochma nen array, das man zum check immer durchläuft. hmm gut, müsste nen dynamisches array sein, könnt man auch gleich ne liste nehmen *grübel* ><


----------



## fadade (18. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

(Sorry, ich melde mich nun doch nochmal etwas OT ..
vielleicht wäre es ja tatsächlich sinnvoll hier im Unterforum einen Programmier-Quatsch-Und-Helf-Thread zu starten bei dem genau solche kleinen Anfragen gepostet werden können  )

@DarkMo:
ich glaube 

2a
1b
3c
1a

ist gefragt, weil bei deiner anderen Variante (die zwar kürzer ist) die Lokalisationen verloren gehen. Dat hatten wir vor Ewigkeiten auch einmal ^^


----------



## bingo88 (18. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

@DarkMo Nein, da du so die Informationen nicht mehr entpacken kannst. Deswegen ist RLE auch nicht für alle Arten von Daten geeignet, da die Daten nach der Kompression sogar größer werden können. Sehr gut geht das z. B. bei Schwarz/Weiß-Bildern (RLE wird beim Faxen verwendet)


----------



## DarkMo (18. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

asöööö, jetz versteh ich erst den größeren sinn dahinter ^^ das soll ne komprimierung werden? ineffizient bei laufend wechselnden "werten" (aus abc würde 1a1b1c -> datenverdopplung), umsoeffizienter, je mehr vorkommen eines wertes aufeinander folgt (aus aaaaaa wird 6a -> ein drittel der datenmenge). jetz richtig verstanden?


----------



## bingo88 (18. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*



DarkMo schrieb:


> asöööö, jetz versteh ich erst den größeren sinn dahinter ^^ das soll ne komprimierung werden? ineffizient bei laufend wechselnden "werten" (aus abc würde 1a1b1c -> datenverdopplung), umsoeffizienter, je mehr vorkommen eines wertes aufeinander folgt (aus aaaaaa wird 6a -> ein drittel der datenmenge). jetz richtig verstanden?


 ja genau!


----------



## boss3D (18. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*



bingo88 schrieb:


> 2) Bei Schleifen die Zählvariable besser immer im  Schleifenkopf initialisieren, das verhindert ungewollte Fehler.
> 
> ```
> for ([B]i = 0[/B]; i < len; ++i) // Bei C++ bzw. ab C99 geht auch for (int i = 0; i < len; ++i)
> ```


Den Datentyp auch in der Schleife anzugeben, mache ich normalerweise nur in Java/C++. Das will ich mir für C lieber nicht angewöhnen, aber Variablen in der Schleife (neu) zu initialisieren, ist wohl nicht verkehrt. 


bingo88 schrieb:


> 3) Erklärung der Schleife
> [...]
> 4) Mein Code liefert übrigens bereits die komplette RLE für den  String (das printf), nicht nur für die ersten vier Buchstaben. Daher  dürfte der Rückgabewert in deinem geposteten Code auch nicht unbedingt  das erwartete Ergebnis enthalten (also bei dir gibt der 8 für die D's  aus weil das der letzte Wert ist).


Ok, jetzt komme ich mit, was  du machst. 

Nur eines ist mir noch immer nicht klar: Die äußere  for-Schleife prüft ihre Bedingungen BEVOR sie in der nächsten Zeile das  count=1 sieht. Dabei stoßt die for-Schleife auf i+=count und hat aber  noch keinen Wert für count, weil du es ja auch vor der Schleife nur  deklariert, aber nicht definiert hast. Wieso meldet der Compiler hier  trotzdem keinen Fehler? Wenn ich für den Schleifenstartwert nur i (statt bspw. i=0) hinschreibe und i zuvor aber nie definiere, geht ja auch nichts und ich  bekomme einen Compilerfehler ...

^^ Ich hoffe, du weißt was ich meine. 


bingo88 schrieb:


> 5) Length = Anzahl Elemente, Text ist in str[0] bis str[length-1]  enthalten. Wenn du mit i <= length arbeitest, liest du noch das  Nullzeichen mit ein. Bei nicht-nullterminierten Strings schmiert dir  dann das Programm mit nem Fehler ab (Speicherschutzverletzung oder  ähnliches)


 Also inkludiert length die Nullterminierung doch. War dann ein Verständnisfehler meinerseits.


DarkMo schrieb:


> bei aabccca müsste der dann doch sowas wie
> 
> 2a
> 1b
> ...


Laut Angabe soll vor Buchstaben, die keinen identischen Nachfolger haben, also nur 1 Mal vorkommen, keine "1" als Zahl ausgegeben werden, sondern nur der Buchstabe selbst. Sinn der Lauflängencodierung ist es ja, das Ganze möglichst weit zu komprimieren und zum Beispiel für 1B bräuchtest du 2 Zeichen, was länger wäre, als nur ein Zeichen für B.


fadade schrieb:


> weil bei deiner anderen Variante (die zwar kürzer  ist) die Lokalisationen verloren gehen. Dat hatten wir vor Ewigkeiten  auch einmal ^^


Richtig. Das Ganze muss ja auch wieder decodiert werden können und zwar so, dass der Originalstring wieder zum Vorschein kommt. Wenn ich alle identischen Buchstaben zusammenfasse, werde ich deren Position kaum noch ermitteln können.

[Edit]
@ DarkMo
Ah, hast es also eh schon verstanden. War noch am Schreiben, während du gepostet hast.


----------



## bingo88 (18. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Das Inkrement wird erst am Ende der Schleife durchgeführt:


```
for (int i = 0;                  i < len;                  ++i)
        zu beginn        vor jedem Durchlauf       nach jedem Durchlauf
```
Außerdem habe ich count ja vor der Schleife deklariert ("int count;"), daher meckert der Compiler da nicht. Und da der Wert erst nach dem Durchlauf gelesen wird, hat der dann auch einen Wert.

Die Length-Funktion liefert die Textlänge ohne Nullzeichen, das ist schon richtig. Du beginnst nur nicht bei 1 mit dem Index sondern 0, daher hast du len Elemente von 0 bis len-1.

```
"A B C D E \0" => Länge = 5
 0 1 2 3 4  5   => Index
```
Bei reinen Texten kann man natürlich die 1 bei einmaligen Vorkommen weglassen. Allgemein geht das aber nicht. Wenn du den gesamten Byteraum bspw. codierst, weißt du nicht, ob das jetzt die Anzahl oder das eigentliche Datum ist. Daher hat man da diese "1A1B2D"-Geschichte. Es gibt da aber Abwandlungen von, z. B. bei JPEG. Da wird nur die 0 codiert, andere Werte nicht (0 tauchst allerdings sehr häufig auf)


----------



## boss3D (18. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

^^ Ok, danke für die Erklärung! Mir ging's nur darum, wo count definiert wird und warum. Dass du es (schon vor der Schleife) deklariert hast, habe ich eh gesehen. 

Der Code sieht (nach ein paar Erweiterungen) ATM so aus:

```
#include <stdio.h>

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

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

    return length;
}

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

    for (i; i<stringLength; i+=count) {
        count=1;
        for (j=i+1; j<stringLength; j++) {
            if (*(s+i) == *(s+j)) {
                count++;
            } else {
                break;
            }
        }
        k=printf("%c%d", *(s+i), count);
        encodedLength+=k;
    }
    printf(" (%d Zeichen)", encodedLength);

    [COLOR=royalblue]ratio=[B]checkLength(s)[/B]/encodedLength;
    return ratio;
}

double decode_runlength(char *s) {

}

/*int main(int argc, char *argv[]) {*/
int main(void) {
    int i=0;

    /* 
    char *s = argv[1];

    for (i=1; i<=(argc-1); i++) {
        printf("%s (%d Zeichen)\n", argv[i], i);
    } 
    */

    char *s = "AAAABBBCCCCCCCCDEABBBBDDDDDDDD";

    printf("%s (%d Zeichen)\n", s, ((int)checkLength(s)));[COLOR=royalblue]
    printf("\nRatio = %.3lf | Percentage = %d %%\n", encode_runlength(s), (int)(100/encode_runlength(s)));    
    putchar('\n');

    return 0;
}
```
Und das hier ist die Ausgabe:



			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



Um die Encodier-Funkion fertigzustellen und damit die erste Hälfte der Gesamtaufgabe zu erledigen, muss jetzt noch folgendes getan werden:
- Die doppelte Ausgabe in der zweiten Zeile (siehe Bild) beseitigen
- Die 1er bei einmalig vorkommenden Buchstaben entfernen (1er sollen nicht ausgegeben werden). Möglich muss es laut Angabe sein.

^^ Bei diesen Punkten bräuchte ich bitte als nächstes Tipps/Hilfe. Das Problem ist jetzt eben, dass die Angabe zwar nicht zwingend verlangt, dass die Ausgabe des Ergebnisses bereits in den jeweiligen Funktionen stattfinden, aber schon stark andeutet, dass sich dies in der main empfehlen würde. Dann wäre alles weitere leichter zu programmieren ...

Und für's Verständnis: Wieso muss ich in der Zeile, wo ratio in der Decodierfunktion berechnet wird (kurz vor dem return),_ ratio=checkLength(s)/decodedLength_ sagen? Wieso funktioniert _ratio=stringLength/decodedLength _nicht_?
_


----------



## bingo88 (18. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Du müsstest sowas machen: ratio = stringLength / (double) decodedLength. Du hast halt sonst ne Integerdivision und da kommt Murks raus. Wenn checkLength den "richtigen" Typ int hätte, würde das auch notwendig sein. Aber dsa gibst u schon double raus.

Den Rest muss ich mir morgen mal ansehen schreib grad aufm handy


----------



## boss3D (19. August 2012)

*AW: [C] Hochzahlen ohne math.h und pow berechnen ...*

Okay, werde in der Zwischenzeit selber noch ein paar Dinge probieren. Die sinnvollste Lösungen, auch um die Programmierung der zweiten Hälfte der Aufgabenstellung zu vereinfachen, wäre es, *die Encodier-Funktion so umzuschreiben, dass dort keine Ausgabe stattfindet, sondern dies erst in der main passiert*. 

Auf jeden Fall dürfen wir, egal was wir machen, immer nur mit dem string char *s arbeiten. Gedacht wäre es so, dass der komprimierte string ebenfalls in char *s gespeichert wird, dann rein mit *s in die Decodier-Funktion und dort wieder umrechnen in den Originalinhalt ...

[EDIT]
Puh, die Ausgabe der 1er bei nur einmal vorkommenden Buchstaben wäre auch weg. Wieder was geschafft.  
Nur leider zählt der jetzt 12 statt 13 Zeichen im encodierten string. Irgendwas wird (noch) nicht mitgezählt ...


Spoiler





```
#include <stdio.h>

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

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

    return length;
}

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

    for (i; i<stringLength; i+=count) {
        count=1;
        for (j=i+1; j<stringLength; j++) {
            if (*(s+i) == *(s+j)) {
                count++;
            } else {
                break;
            }
        }
        [COLOR=royalblue][B]if (count==1) {
            l=printf("%c", *(s+i));
        } else {
            k=printf("%c%d", *(s+i), count);
            encodedLength+=(l+k);
        }[/B]    }
    printf(" (%d Zeichen)", encodedLength);

    ratio=stringLength/(double)encodedLength;

    return ratio;
}

double decode_runlength(char *s) {

}

/*int main(int argc, char *argv[]) {*/
int main(void) {
    int i=0;

    /* 
    char *s = argv[1];

    for (i=1; i<=(argc-1); i++) {
        printf("%s (%d Zeichen)\n", argv[i], i);
    } 
    */

    char *s = "AAAABBBCCCCCCCCDEABBBBDDDDDDDD";

    printf("%s (%d Zeichen)\n", s, ((int)checkLength(s)));
    printf("\nRatio = %.3lf | Percentage = %d %%\n", encode_runlength(s), (int)(100/encode_runlength(s)));

    putchar('\n');

    return 0;
}
```


----------



## Anilman (21. August 2012)

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

Hallo ich weiss nicht ob es hier her passt.
Ich habe einen text im forum in bf3 gefunden und wollte fragen wie man sowas hinbekommt.

Google gibt mir auch nen error 413

da dieses symbol groß ist und überdeckt habe ich mal platz freigelassen
zwischen den Zeilen steht im the best 
LINK von der quelle
Hier mal copy and paste.










'̵̧̛̫͉͖͚͈͎̌ͨͮͦ̾͊̇̏̌ͤ̀̌̏̿̇ͦ̀͟ḿ̤̭͍̻̖͚̤͇͈̲͕͉̯̞͎̫̱͕ͦ͗͒͗̍̎̆ͩ͌́́̕  ̧͇͈̞̎͋̍̎͛̚ͅṮ̢̗͖̗̣͎͙̤̗̭͌̀ͫͦͬͣ̔̿̆ͩͥ͑ͦ́̀͜͡ͅͅḨ̠͓̲̥̪͈̣̱̦͍͚̝̱ͫ͐ͣ̌ͯ̊̕̕E̦͙̯̜̪͇̯̼͖̝̞̜͕̋ͪ̋̇͌̋̃ͪ͗̋̉͑̀ͦ̓ͦ̀   ̶͖̠͈ͤ͆ͭ̿ͯͯ̎̋́ͭ̌͊̓́̓ͣ͜B̸̡͎̤̥͉͉͉͚̰̟̂͊̽͆̌ͥͩ̓̉͐ͪͫͨ͟Eͯ̉́͌ͭ̂̽ͭͫ̿͆ͩ̈́ͨ҉̸̼̰͖͉̦̀͡͠S̵̻̘̭͓̻̥̲̟̫̦͍̦͈̝ͩ͛͂ͯ͌̏ͨ̈́ͥ̍͐̏ͨͣ̍̕ͅT̪̟̰̞̪̽ͤ̓̓ͯ̃͑ͣ̂̂̏́͊ͩ͛ͦ̔ͣ̈͟.̸̨̥̠̬͍̼͈̠̜͇͈͂ͦ͋̒̏͠͝Ḭ̶̟̲̥̽͑͌ͩ́̈ͨ̃ͥ̈̆̆͋̋ͬ͜'̧̢͉̻̭͓ͦͣ̽̿̉̀͟͝ḿ̹̦̯͖̞̥̥̌̓̋́ͬͥ̄͢ͅ   ̴̷͔̠̗̲͈̖̟̻͛ͤ̏́̿͒͊̌́͐ͥ̅̚͜͠͝Ṭ̮͔̩̩̱͎̥͒́ͫ̆͊̌͞H͗͋̇̆ͦ̿̓̎ͧ͛ͪ́̚͟͢͏͓̮̤̱̳̹E̶̪̳̰̥̩̪̦͍̮̻̖̱ͧ̄ͨ͌̓̈̇ͣͣ͗ͬͫ̇́͝   ̸̯̰̬̗͍̤̮̤̺̬͖̩̮̪͉̩̆͑̈́̿͒̏̽ͪ͗̇̅̍͒ͧͨͨ̔̾͠͡Bͩ̈̊̑͐̑̒҉̬̪̳̘̱̗̝͎̖͢ͅE̴̡̦̬̙̳̤̟͈̜̹͎̩̺̩͕͕̪̭͕̎̎ͪ̀̑̎ͣ̓͒ͤ̆́ͮͨ͂̓́͘͡Ş̴̠̩̤̞̝͖̞͇̲͉̠̯̜͍̗̎̂ͩ̾ͦͦ͋̎ͮͨͩ̌͆͜T̸̨̨̟͎̙̬̱̖̳̭̾͗̔͊͌̅̋ͬͥ̓̈́̓̒̓̉̍̒ͅ.̸̛̲̫̩̯̖͕̼͖͉̔̿ͩ̄́͢Ị͕̞̲̝̯̩̥̋̄ͬ̄̽̌͋͢͡'̡̉̅͒ͩͣ͗̔͊̋̄͋̏́͏̤̞̬̺̀m̧̧͖̹̙͇̖͉͈͛̐̇̆̍̊̾ͭ̎͂͋̅͑̓̐͒͊̔̕͜͞   ̶̢̢̱̗̲̣̞͕͓̍ͭͥ̿̐ͮͪ͂̈́́͝ͅT̷̆̓̌́ͯ̆ͧͥ̔ͧ̓̆҉̲̭̤͓̮̬̤̻̰͕͈̩̹ͅHͫͭ͗̊ͮ͐̄̍ͪ̾ͫͤͪ͆́҉̵̲̱͔͔̹̮̟̘̝̝̣͖̠̭̖̖̰͟͠Ẽ̢̢͚̤͖̙͓̦̓̈̄ͣ̊͋̈́͊̀͘   ̷̡͉̮̹̰̤͖̺̘̬͍̦͚̳̗̩̮͕̫̂͂̐ͩ̃ͅB̴̛̟͍̯͚̗͍͎͓̰̳̫̣̉̓̒̓̚̕͟͡E͈͇̘̲̳̹̥͓̻̼̠̖̣̲͚̣̋͊ͦ̅͋͒ͬͫ̿ͯ͗͢Ș̡͉̮̤̩̤̬̥̤͚ͮͪ͛̃͑͐̍̄́̚͟͡T͓͎̣̟͇̘̤̯̩ͣ͑̆́̽ͯ́̄̈͘͜͢.̸̵̬̙̳̘̬̲̠̪̬͕̭̣͓̲̤̖̤͕͍̇ͭ̄̅̒̂́I̬̗̺̯͓͍̞͍̦̮̪͙̥̼̺ͣ̍̑̆̈́̈̓͂̍́͢͟'̵̧͇̠̮͕͕ͬ̃͒̀͛̿̒͋̈́̆͟ͅm̶̵̘̞͖͎̫͙̤̬̹͙̗͈̱̗̻̤͕̰̟̽̂ͯ͆ͣ̅̚   ͭ̃̅̎͊͂ͨ͒ͣ̽̂͗҉̸͖̹̱̩̟̰́̕T̵̨̛͙͍͕͔͕̩̦̒͆̈ͤ̍͆̑́͊̉ͫ́ͫ͊̀͝Ḩ̴̠̥̜̉̎̆͒͛ͣ̇͊̔ͯ̀͘Ę̴ͥ͒ͫ̄̀͟҉̝̣̖̜̻̦͍̮̲͓̪̖̜͈̰ͅ   ̧̡̉̊̉ͤͤ͒̀̿͑ͬ̓̑̏̚͟͞͏̭̫̙̯̰̘͓̥̰̙͎̤̺͙B̴̰̳̹͓͙̍ͬ̅̈́͜E̵̥̙̳͈̱̝̭̘̞ͫ̒͌ͥ͋̽̒̍̇͐͊̄̏̋̈S͛ͬ̿͑ͩͯͧ̿̄ͯͬ͑̒͐͋͟҉̳̹̙T̴̵̗̫̖̞̼͓͍̦̖̜̲̮͈͊͆̇̃̆͆̿ͩ̚͠.̴̨̧͓̳̫̞̣̟ͧ͋ͬ̾͑͊ͥ̊̑̀͒̉͑͊ͨ̈̂͜͟Į̶̵̺͉̝͇͈̭͔̻̝̣̱̮͓͖̘̺̀ͨͪͧͯͦ̓́̋̓ͦͮ͒̓̌ͭ͊̑'̵̸͈͓̺͎̹͒͗͋̊́m̷̷̯̖̼͔̭̟̳̥̲̙̞̠͚̥̹̎̉ͧͭ̾͊ͨ͌͑͞   ̨̭̞̪̦̰͈̭̣̖͉̦͍̥͛͊ͯT̴̵̥̥̺̗̗͇͉̖ͣͧ̊̅͋̎̾̃͜H̆ͮ̋̍̅̆̄̍̏͑̾ͭ̍̆͌͏̬̦̪̲̳͢Eͣ͊ͪ͊̂ͫ̒̎́̚͝҉̶̥̺̮̙̞̘̣̜͔̜̟̣̝̱̕   ̶͎̹͍̿ͧ̽ͧͣ̎͆͘͢ͅḂ͗̊͐̅ͥ̏̊ͣ̐͏̷̜̫̠͚̬̯̟̗͎̠̭̦̫͖͖̮͟E̤̠̥̻̺̤̤̗͇̔̔ͫͤ̓̃ͤ͢͝S͛̓ͥͩͥ̀͊ͭͫ̋̆ͣ̂͒̌ͮͥ҉̶̸͙̣͙̠̖͈̫̱͙̝̺͍̝͍͜Ţ̛̛͙̹̗̝͍͔̘̱̟̺͕̖̘ͦ͊̽ͣ̈́͆ͭͭ͌̍.̸̧̨̬̻̟̼͛ͥ͗ͦ̉̃̎̾ͦ̀̽ͩ́͝I͇̝̭̮͇͕͓̩̱̯̦͔̼̭̝̤͔̎ͧ̓̍̾̉̓ͧ̊͞͠ͅ'̡̡͙͎̤̬͍̘̙̫͉̙̦̩̬̻͍̣̦̓ͭͯ̅̊͟͞ͅm̨̜̬̯̼̭̪͓̩̹̣̩̮̙̱͓̰̟͓̾ͧ̑̑ͩ̃̓͐̆͛͛ͮ̃ͣ̄̚̚͜͞   ̷͎̜͔͙̠͍̱̩͕͇̱̱͈̰̟̱̦̯ͯ̽͐̅̋̀͐͋ͬ̐̎̀͟T̴̸͕̯̮̺͇̲̬̖̮̺̫̈̔̿ͬ͂ͣ̀͆H̴͖͔̪͍͖͕̤͖̟͈͍͖̬̱̗ͥ̅̒ͤ͐̚͘͟Ě̇̈̉͆ͮ̒̓̓ͪ͛ͮ͋̆̆͏̸͉̝̪͖͈̱͚̫̣͉͖͕͉́͘͢   ̨̛̳͇̱̜̳̰̫̩̙̪̲͓͓̹͌͑̌͂ͤ̍̏ͩ̿ͮ̕͡͝ͅB͚̻̝̦͙͙͍̯͓̿͒̿͆ͮͦͬͯ̉ͬ̍̉ͬ͗̆̓͗̊̕͜ͅͅĘ̶̩̤͚̭̣̥͛̐̆̑͡S̢͚̗̩̦̲̻͎̬͈̞͎̩̿ͬͮͣ̑́ͫ̆͒͡͠ͅTͬ̈́ͤͯ̽̏͆̎̒̈͗͋̋̽̈̑͗̈̀͢҉͇̪̠̘͈͚.̴̶̣̣̘̙͋ͧ͗͋ͦ̂͌ͤ͗͛͌̐͋͢͞Į̴͓̝̺̘̞̣̯̫̭̜͚̣̱̔ͨ̐ͫ̌̊̑͌ͮͬ̒ͭ̚'ͥ̔͌͋ͣͬͧ̽ͧͧ̍ͨ͌͋̃̈͏̡̲̤̻̩͜m̷̧̰͔̗̗͈͉̳͓̖͐̇̌̔͑̔̈̋̅͒ͨ͑͆̐̚͘   ̷̣͙̟͖̦̮̳̹̮͎͖̲̝̪͖͚̻̻͊͒̽ͪ́ͩ̆̾̾ͬ͆̀T̶͖͉̬̟̬̮͙̺̝͓͔͓̦̙̮̼̳̍ͤ͒ͧ͐͋̽̏̕͞ͅH̷͔̩̟̼̝͖̫̤̤̮͈̬̠̰̼͍͎͈̰ͭ͑ͯ̉̄ͮ͊̾ͥͥ͑ͨͤ̚͝͞Ę̊̈͋̒̍͂ͩ̓͂͂̇̽͆̃̇͋͏̨͜͏̬̳͖̟   ̷̨̹̮̱̞̫̝̜̈͊ͦ͌͌͐ͥ̇̋B̡͈̥͖͉̪̽͋͛ͯ̔͗ͩ́Eͬ͌ͪ̐̊ͯ͗̉̇̃ͨ͏͏̵̨̫̠̜̟͚͔ͅS̎ͯ̐͛̀̍͆ͬ̓ͮ͑͂̄̑̋̓̚҉̢͚̱̦̻͇̭̱͇̩̥̻͇̗͈͈̪̫̀͢͠T̶̵̴͈̻͙̼͙̳͚̭̤̩̯̩̹͖̮̰̲͗́͆̂ͤ̌̅͡.̓ͥ̄̔̃́̐ͦͣͬ̅̌̓͏̶̗͇̻̰̞̣̳̲Į̛̱͖̍̓̋͛ͥͬ͑ͥ͐̍̿ͫ͋ͬ̉̀͛̕͜ͅ'ͨ̓͌̾̐̔͛̇͆ͨ̿͌ͬ̾̏͂͡҉̴̗̞̝̖͖̙͡͞ͅm̶͆͐ͫ̊ͥ̾̑ͩ͛̑̓̐͂̋͛̀ͦ̑҉͡͞҉͓͔͕͉̲̯̩   ̨̔ͮ̒̏̔ͣͦ̆ͯ͌̑̄ͮͨ̄̚̚͘̕҉͎̙̼̥͍̠̙̘̼̤̭T͕͎͕͙͔̣͉̠̜̱͖̼̗̲ͮ̔ͩͨ͘͠H̡̧̳̱̞̱̻̝̺̻͉̰͖̣͎̿͒ͣ͑̊̍͂̃́͞E̴̷͍̭̤͍̘̲̝͍̻̞͍͔͈̮̦̲ͬ̄ͬ̅̅ͯ́͝ͅ   ̴̨̨͈̺͓̙̰̆ͮͨ̆ͥ̀̎ͬ̀͜B̶̶̩̰͈̮̰͎͍̙̱͈̫̳̘̬͕̜ͩ̓̐́͗̑̋͊ͭ̉͑͟ͅÉ̸̡̛̘̬̭̻̝ͯ̅̀̓͊ͭ̿̓̐ͦ̓ͣ̓͡S̡̭̭͓̭̣͈̲͓̬̞̥̲̠̮͌ͥ͆͛̀ͤ͛ͩ̐ͤ̍͂͛̀̕͟ͅT̨̡̳̰̬̲͕̹̎̐̈͌ͮ͛̒̏ͬ́ͤ͜.̷̎̊ͥͭ͗͝҉̠̗͚̥̦͉̼͍̥̕I̴̷̤̻̟͗̇̉̊͛̏͘͡'̓͐ͪ́͆̇̂̃̋̓҉͈̣̦̻̫̺͕̤̠͕͔̹͍͓̪̞̮͘͢m̸͔̙͇̞̳̗͓͇͓͙̙̹̙̗̓̿ͭ͊ͣ͊͞   ̹̖̣̺ͦ̔̓͒̂̋ͣͩ̅̽̊̎̿̎ͨ̀̚͜Ţ͐̒̈̍̈ͯ̓̓̉̃͏̭̻̹̣̝͖̪͎̭̞̫H̛̩̼̰͕͓̠͚̟̺͍̬̬̣̣̼͖ͤͤͧͤͮͯ̒͝Ẻ̛͛͒ͨ̽̔̄͌͂ͯ̌͗̈ͮ̔̌͂́҉̢̠̺̮͈͙̯   ̸̧̥̦͕͙̄̉̄͆̏͛ͭ̀̓͆ͥͮͦ̌͆̓̂̚̚͘B̶̾̌̅̂̂ͣͣ̃̾͒͊͌̄ͤ͌͆͛̓͌́̕҉҉̙͎̝̘̬̞Ě̯̱̳͇͕̼̣̲̗͗̋ͨ̐ͤͨ̄̆͆̃̊̏̆ͮ̚̕͡͝͡͞S̏̂̍ͭ͌͆ͭͤ̀҉͔͚̭̳̠͇̩̮̭̩͓̲̳̘ͅT̶̳͕̲̹̼ͣ̃̂͑̃̎ͫͤͧ͑͊̒͊͛̈́̔͝.̺̝̠̰̯͓̥͇̠̗̽̇̎͂̇̄ͤ̎ͪ̋ͦ͌̎̇͜͢I̦̮̳̯̹̙̰̺͔͍̙̣͖̩͙ͨ̓ͨ͆̃̃̾͡ͅ'̢̛̭̜͇̭̩͑ͯ͊ͣ̔͒̾ͨ̃͊̓͒̋̑͊͘͟͠m̡̧̮̟͔̺̳̞̼̜̤̲̲̠̜̬͓͙̥̱̆͑̎͗̅ͫ̿͗ͯ̉̈́ͨ̈̈́ͤ̋   ̸͙͔̝̟̝͓̰̹͓̮̌̅̃̂̂͘T̴̨̙͙̩̬̪͓̠̟̝͛̈́͆͐̑͒ͧ̾͆̇ͤ͒̽̒ͤͭ̅͂̀ͅHͮ͂̑͏͉̫̺̙͖̠͉͙̘̩͍̙̘̥͠ͅE̴̢ͭ̊̏ͮ͌̃̇͋́͏̘̪͓̰͉̺̞̭̙͇͓ͅ   ̶ͦ̅̏̑ͦ̿͂͒̽͝҉̤͉̟͚̟̫̩͓̫̬͉̖͔̙͔̮̩̼͖B̳̙͇̩̯̩̙̯̘ͤͧͤ̔̍͊̄̉̐̆̀̈̆̓̌̅͗̂̓̀Ȩ̧̢̟̫̰͎̭͍̠͕͙ͧ͊͛̄ͧͯ̋̋̑͟S̸̢̧̺͔͕̲̼̩̪̯̠̩͔̣̬̰ͦ͒̅̊T̵̪͔̱̪͓̰̖̘̞͂̿͌̓̐̍͐̑͊ͤ̚͘.̵̜͇̠̜̞̮̜̏̊ͬͦ̎̍ͧ́̇ͫ̀̎ͧ̏ͣ̎͟Ï͇͕̼̖̳͈̫͓͕̖̲͐̌̑ͨ͂ͥ͑̽ͦͦ͑̍̈ͭ̉́̕͡'̴̵̡̬̙̠͖͖̅̅͗͐̏͋ͤ̏̐̌m̸̶͇̤̘̟͖̰̜̪͔̪̗̰̥͉̱̞̓ͪ̃̓͌͒́̔ͣ̿͆ͩ͌̂̐̊̄ͮͅ   ̵̡̨̫̬͔̯̃͛ͣ̐͊̈̕͢Tͥͦ̄͆ͨͭ͋ͣ͒̍͂̚҉̷͘҉̥͇̠̳͈̝̪̝̪̤̥̲̦̹͜H̷̴̏̆̐̈҉̳̗̬̬̜͜͜ͅE̛͈̝̲̯͖̣͎̼̲̽͛ͧ͛̒̔̀̂ͭͧ͂͊̓ͣ́͞   ̭͍̠̖̩̯̞̼͕̺͔̙̻̟ͨ͆̀̆͆̾̅ͧ̀̇̾͊̍ͪ̓ͨ̋̊̓͜Ḇ̵̩̮̥̟͔̻̌̿̍̿̓̀̓̑ͩ̉̾̕̕͜Ȩ̞͚̖͇̭̦̗ͬ̎ͮ̊̆̂͐͒͛ͥͥ̿͗ͩSͨ̑̾̓̓̅̏̄̋͋́̍̎̽͌̓̓̚͜҉̵̯̹̯̻̹̫̦̳̻̫̣͖͉͔̫̦̀͘T̹̣͉̭̠͎̤̥̜̝͕͖̖̃ͫ̽̋ͯ͐͊̇̾ͧͮͬ̽̀̈́̍̽̀͟ͅ.͛͒͒͛̑̊̽͊ͨ͌ͭ̚͏̛͖͚̦̰̦̟̲̻͔̭̣͇̜̻̮͇̀ͅͅĨ̴̧̱̮̤͖̲̝̰̜͔̝̗̳̺̺͎̉ͨ͌̽̈́̎ͧͫ̆̀ͅͅͅ'ͩ̓̆̄ͯ͊̃̐ͩ̒͆̊̚҉͏̗̳̥͉̘͔̺̣̯̣̟̯̝̞͘͟͡ṁ̸̨͇̞̺̖͔̟̺̗̎͂̂ͥ͂ͪ̂͗́̈ͯ   ̶̡̺̗̮͎̌̏̀̆̓͂̒̏̉ͫ̍ͬͯͧ̊ͥ̚̚͜͝͝T̵͖̳͉̰̠̪ͨ̏ͫͧͪͧͯͧ͋̉́̕͜Ḧ̴̬̟͙̥̩͚́͋ͩͦ̄̉̓̾͂͌̄͋̾͒͛͐ͮͨ̋ͅĘ̛̛͙̣̖̟͔̘̰̥̋ͤ͆͊͗̾͌̔̇ͣ̅̆ͧ͆̀͞   ̸̷̧̭̹̯̮͍͎̤̖̠̹͔͓ͮͤͣ̒̊̌ͣͮ̐ͭ̐̈́̆̿̅ͥ͢͞B̨̥̰̱̭̜̗̳̘̙̝͓̻͓̫̯̤̫̘̉͋̓ͭ̈̈́̐̈̈ͮͮ́Ę̶̝͓̘̯ͤ̆ͥͯ͛ͮ̃͆̃̃̌̂̿ͫͨͩͥ͡S̵̳̰͓͇̠̰̃̊̿ͫ͘͟͝Ţ̸̴̙̬̥̳̲͕͈̺̰͕ͫ͊ͯ͐̑̑̎ͪͦ̊ͥͬ́͂͗̈ͬͦ͗͟.̵̡̺̹̜͈͙̟̰̹͙̜͇̠̦̣͈̝̔ͨ̓͂̌ͤͪ̀͟͜I̴̱̤͙͎̝͚͗͊̆ͤ͌͛'̣̦̤̩̳̩͈̭̰̓ͥ́̌̉̉̔͐̈́͆͗͐̚͢͞m̶̛̪͖̜̤̙͓̥͓͖̜̞̦̥̑̊̐͋̓̄̉ͩ͐̓ͤ̉ͯͣ͊ͯ̉́ͅ   ̨͕̯͖̗̠̮̯̻̤̥̭̲̽́̿ͤ̒̍ͣ̄ͣ̄ͭ̍̐͗̏ͪͫ͠͠ͅT̷̛͙̼͕̖̳͍̼̳̘͍̩̤̩͈͇̣̗̊̾͛̎͋̃̈́ͭ͞H̛̺̳̣̙̩͖̥͈̳̜̯͇̒͑̎̎̑̒ͬ̐̌ͣ͟͡E̼͔̥̪̩̠͙̤̻̻͓ͣͦ̅̂ͤ̿̏ͩ̎̀̕   ̜̱̤̘̳̦͚̘͉̩͕͍̻̓ͪ̇̆̃̓͛̏̀͝B̧̢̗͔͖͙̖͖̰͔̖͍̜̻̦̲̩̻͙̥͒̍͒̇̋͛͋ͩ͑̓ͯ̍̚ͅĒ̴̛̟̘̟̖̠̖̙̗͒ͫ̔̏S̳̱͍͕̀͆̈̎́́̕͘T̡͖̞̱͇͕̦͙̭̤̏̃̄́̀ͯ͂ͭ̑ͥ̓̈́͆̓̾ͦ̚͢ͅ.̵̸̸̛̒͛͂̇̓̿̊ͨ͏̙̬̤̹̩͔̤͖̰̱̝͚̼̮̥͖͚Ȉ̡ͤ͊ͤ̑̆͊ͪ̈̀͏͈̺̩̣͎̗̫̗́'̸̧̢̧̣͚͔̪̱̩͖̣̖̖̙̙̥̤̙̪͚͗̂̾̔̑ͤ͛̇̃̏͂ͮm̢̡͍͍̼͕̝̥ͣ̍ͪ͋͛͊̓̌ͫ̊͂̐͝   ̸͚̭̩̮̽ͤ͋̅̏̽̈́ͮͨͭ̚̚͝Ţ͓̙̭̲͎̠̰̙̯̝͕̋ͮ̔ͥ̿̀̔̾̔̔̓͐̓͋͊ͣ̾͟H̷̛ͤ͗͛ͦ̀͘͏͉͔̝̯E̩̞̩͎̼͇͐ͨͣͮ̒̈́́ͯ̒̂̋̉ͣͭ̂́̔̀̀͠   ̢̡̢͓̲͓̳̰̯̣̳̫̥͍̙̞̲̳̙̲̠͉̇͂̾ͩ̅͗ͨ̐̓́̚Ḇ̧̠̤̙̟̰̱͇͓̳͉̭̘̭̘̤̇̑̃̓̈̔̌̂̀̊̔͊̾ͣ͋̇̆͗̀͞͞Ȩ̶̟̬̥̼̹̟̭͓̟͖͉̮̖̍̇͌͐̀͛̇̐ͬ̇S̴̜̟͉̞̰͉͉̮͓͉̹͕̬̱̿ͩ͛ͯ́̚T̸̨̠̺͚̩̬͒̾̃̋́ͮ͗̓̈́ͧ̊̍ͪͥͭ̈́́͢͢.̵̛͕͔̘̥̣̜̺̗̻̺͈͇͛̉͂̈́ͩͦ̋̃͟͟͡Į̶̷̖͇̭̻͙͐̃ͪ̋͗͂ͥ̈̋'̒͗ͣ̂̾̍ͫ̒̈́̚҉̨̩̙̙̝̬̞̘̫̗̜͙̙ͅͅm̛̯̻̭͙̣̦͇̫̬̭͎̫̯͎̹̆͋̎͌ͪͫ͐̒̓͟͟ͅ   ͖͉͇̳̟̖̯͗͂̍̿̾̉̇̅ͥͣ̃ͨ̈́͂͌̐̚̚͞͡ͅͅŢ̞͈̖̼̥̲̥̞̰͗̃ͪ̇̏̀̔ͬ͂͝ͅH̷̨̍͂̌ͨͥ̓҉̵̙͇̰͓̮̭̤ͅȨ̲̙̘̖͓͕̝̟̙̘̺ͨͨ̎̏͗͑̎͢͢͜͠   ̸̨̨̛̭̻͙̘̻̣̼̮̣̳̣̭ͦ̈́ͮͫ̑ͮ͑͑̑͊ͤͭ̒ͨ̀ͅB̴̞͚͚̫̝̟̪̣̯̳̲͖̲̞͐̓ͬͭ̔̉͡E̜̞̲̘̣̺͓̣̘̬̪̱̟̯̗̦̥ͧ̀̇ͪͧ̆̉́̓ͪ͌͘͡ͅS͙̜̠̠͎̺͇̍ͭ͆͒́̑͗ͫ́͜T̛̠̥̺̩͈ͣ̊̉ͫ̽̎̂͌ͧ͑̇̏ͣ̃̄̔ͥ̀̍̀̕͘.̴̛͙̗͙̦͙̤͓͚̒́̈́̃̊͒̈̐̌̉ͥͤ̔ͪͣ̉̉̀͠I̴͙̩̮̺̮̺̘͗̏͛̓̕'̸̸̧̜͚͈̗̭̬̰̯̩͈͂̆ͣ͒̽̀̿ͦͣ̑m̢̛͖͍̹͈̩̥͈̤̼̫̠͖͕̠̄ͦ͂͆͌̌͒͋͆͋́̋̋̍ͭͣ͐̀̕ͅ   ͆̽͗͑̇̌ͥ̿ͮ͒̿͞͠͏̫̪̮̥̱̲T̸̢͓͇͉̪̰̝̣̭͚͙͔̿ͮ͋͒̏͛̏̽́̈̓̃̍̂̆ͧͅH̨̨͚̖̟͎̝̯̲̦̞̭̯̪͇ͩ͌́̐͂̐͛̿ͮ͌ͫ̅́͊̅́͠Ě̵̬͇̻̰̜̪͔͕̇̀͋͜͡͞͠   ̛̪̪̙͇͇̺ͬ̿ͪ͑͛̇̏͒͋͒̿͐̈̈́͊͌̇͒̕͟͠Bͫͭͨ͋̎̉ͨ̉̅͒ͮ̿̉͋ͬ̂̚͏̬̣̫̱͚̗̙̣̣̻̣͙́ͅE̡̧̡̧̤̥̳͉̳̬̳̫ͥ̉ͭ̂̊ͪ̄ͦ͑͆̑̅͌̃̇ͩ̀ͅS̛͔͕̮͈͎̰̹͚̙̯̙̹̼ͨ͑͛̒ͤ̚͞͝͝͞T̵̷̠̱͙̮̩͙̰̙͙̬̮͙̘͖̰͇̠̓ͣ̉͛̏̊̿ͤ̔̓ͦ̌͡.ͮ̌ͮ̌́ͨ̽ͪ̇ͦ̓͋̃́̍̒͌̚͟҉̫̹̝̭̩̲͍̟͓̜̠̼̝͖͔̹͖̪̤I̻̜̙͍̰̱̼͈͇̘̯̙͋͆̔̋̈ͣ̇ͨ̍̎́͆ͫͩ͝͡ͅͅ'͑̇͆ͦ̇ͤ̔̓̏ͩͦ͋̈́ͩ̂͜͝҉̱̘̠̠͙̕͡m͕͍̞̼̙͔̳̮̜̥͙̳̑͐̾̀̐ͤ̏̂ͤͮͯ̐ͯ̏͜ͅ   ̷̢̘̥̲̻̮̫̝̟ͮ̊͂̅ͫ͐̉̓ͥ̍ͩ̄̈́͂ͮ̑͗ͅṮ̳̜̳̳̝̙̘̱̭̠̖͕̫̓͑͋ͪ͂̓ͯ̌̋̆̕͟͜H̶̪͍̰̖͓̼͔̜̭̳̻̯͚̋͋͒̆̈͊̆ͭ̀͜E̵̻̝͇̠͔̣̭̩̥̭̊̒̿ͫͫ̀͡   ̨̩͈̞͖̳̬͍̯̱̩́̾̇̿ͫ̑ͮͥ͆̈ͮ̊̓͟ͅͅḂ̵̸̷̢̠̥̰̰̤̣̩̯̜͍̙͈̗̠̪̘̫̏ͣ͋̽͗ͮͪ̑ͣͦ͊̀̌ͩͣȄ̸̤̱̮̝̼̰͖̗̲̘̰̹͔̰̂ͥͨ͑͛̽̾̾̉͂̒́́̀͜ͅͅS̵̴̤̦̬̲͈̰͉̫͈͍̟̞̻̘̳̻̒̽̍̑̇̑̓̚͞ͅT̛͔̺̮͉̙͌͌ͥ̎̃̾̍̔̿̀.̨̅ͧ̒̅ͭ̅̈̈́͂ͯ̎̈́̇ͣ̚҉̴̧̣͇̦͉̣̥̻̫͚̹ͅI̵̢̽̊͐̐͛̉̍ͧ́͘͏͚͔͚͚͇̗͙͕̱'̨͕͚͕̪͕͕̦̭̺͕̠͔̣̝̲͉̓͆̍̒̔ͦͭ̍̓̓̄̀̐͑̃̌̚͠͡mͭ͊̉ͫ͆̑̏̓̉͌͘͏̪̥̼͙͈͉̜̙̬̙̝͔ͅ   ̡ͬ̇ͯ̀̾͆͒ͣ̈́͋̎͗̊̇͛̽̈́͂͏̲̭̖̳̰͎̫̺͕̼̼̤̭̝T̏̊̀̓̈̅̅ͤͩͥ̑ͣͫͤ͌̈́́͠͝҉̢͓̤͓̼̖̜͉̝͇͕ͅH͓̬̟̼̪ͫ̉̇̒̂͂̓ͮͫ͒̑̔̿̈̍́͝E̡̡̡̪̲̹͋ͥͨ̊́͑̒͂̈́͋̋̿ͤ͛ͅ   ̴̸̸͖̣̼͍̠͖̘̏̎̃̽̽ͬ͗̊͊̂̇͂̕͜B̸̛̖̫̘̟̺͎̙̹͙͍̐ͭ͌ͤ̉̄ͭ̒͑̐̈͒ͪ̇̒ͩ̔̏̒̀̕͜ͅE̶̷̘̦̼̩̥̰̼ͭ̈́̇ͤ́͊̓̾̆̌̿̈́ͤͣ̀͘͠ͅͅS̛̙̼̦͕̮͉̭͖̙̰̖̜̆ͪͭͪ̄ͬ̆͆̽̉̍͌̀̉͞T̵̨̼̞̝̟͓̭̠̣͓̣̀ͫ͂́͋̽ͬ́ͧ̂͂.̢̧̨̪̹̙̟̱͎͖̣̹̲̤͓͈̼̔ͪ̃͊͌̏̋͋ͦ͞ͅͅI͐̀̋̆̚͏̳̱̪̯͍͕̰̰̬͟'̧̼̠̗̫͔̂̾̊̒̂̽̈͊̆̎͊ͧͥ̉͝m̷̢͔͔̰̭̼̱̙̳̱͐̉̇̀   ̍ͩ̎͆ͨͪ͑̽ͣͦ̍͠͏̻̪͍͙̬̗̱̮̳̜̪̕͢Ţ͚̰̦̯͎̼̩̲̬̪͎̖̟̦̬̪̝̭̂̓̌̔͊̓͒͂̌̄̎ͮ̋̎ͩͩͩ̕͘͝H̵̨̱͓͙͙͙̩͖̖͕̬͇̍̈́ͩ̋̚͘͟͝È̢̡̻͎͎̩̭̭̬̠̜̱̄̉ͥ̀͐́̕͡ͅͅ   ̸̷̖͎̗̝̘͔̙̱̲͓͆͒ͭ͌͌̌̊̂́͊̓͆̀̚̕͟͝B̵̢̟̬̩͎̳̻̙̻͎̞̰̲̤̅̅ͯ̚͜E̵̥̘͎̦̙͈̱̝̹̮̣͈̅ͤͫ̾ͤ͊̊̓ͬ͐ͯ̾̐͆̈̃ͪ̕ͅŞ̨̡̭͔̤̪̳̱͇̻͇͕͚̗͉̜̼͈̖̘̾̐̍̓́̉ͣ̏ͨ͂͞T̷̶̛̲͎͎͍͍̻̈́̅̓̇͗ͥͩ̄̇́ͭ̿ͬͬ̅̈́̂̋́͝.̴̨̻͚͕͇̳̙ͤ̈́ͤ̔̄͊̇̃̂̅̅͗ͤ̉ͪ̿̊̀͘͟Ĭ̴̸̛̹̪͇͈̥̜͎̹̝̏ͯ͆͂ͣ̀͆̌̓̉ͮͨ̄ͯ̓ͯ͠͡'̸̟͚̩̺͎͊͂ͫͫ̋̋͆̓̉̅̄̇͐̍͐͌͐̎̀̚ͅͅm̸̡̱͇͎͕͚̣̭͔̥͈ͯ͌̉̕͘   ͊̅ͨ̎̎͗̇̑͗͝͏̞͔͔̫̯̪͔̥̻͈̼̙͉̻͘͢Ť̢̼̰͖̋͒ͪ̓͛̀ͣͯͮ̈́̇́̏͋ͣH̹̭̭͙͖̱̞͓͉͌͛̀ͥ̀͡ͅẸ̴̴͖̣̩͓͚̳̝͎̙͕͈̅̋̔̑̃̇̄͢   ̴͈̲̗̘̬̘̫͚̰͔̭̳͉̫͊́ͩ̌͊̄̂̚͘B̷̫̱̪̯̟̙̔ͤ̉̎̽̑ͮ͗ͤͮͪ̎̂ͮ̄ͤ͢͡E͐ͫ͊ͩ͌͊ͧ͟͢͏͖̬̯̲̜S͊́̓́̌ͯ̃̋̓ͥ͋ͣ̏ͭͤ̀̽͒͡͏̟̜̞̥͝T̴̢̻͖̠̖̬̟͕̝̬͖̪̘̣̠̟͙̈́͛̉̑̆͐͝ͅ.̸̴̖̱̼͚̞̥̠͇͇͌́̅̇̍̏̐̅̂ͮ̈̆́̍͌̚Iͥ̽̉҉̸̴̘̹̞͎̤͓̩͚̬̺͎̲͘'̢̣̭͎̹͓̠͍͙̻̫͙̝̣̦͐ͥ́͆̌̓ͪͪͥ͂̋̾ͭ̿ͯ̐͑̚̕ͅm̬̜͈̩̰̘ͯ̂̐̌̂ͣ̾̾͋ͬ̉̌͛̇ͣ̓ͧ̑͘͢   ̴̷̰͙̺̙̳̙̳̗̖͙̬̼͈͇̜̎̃ͪ̾̃̏̽ͯͭ̊ͪ̈̊́͟͠T̨̨̝̻̮̙͖͔͕̖̱̟̹͍͐̔͋͢ͅH͎̜̗̜̺̲̣̰̄̋ͭͥ̎̔ͧ͂͊̅̌ͭͮ͜͜Eͨ͒ͫ̔҉̴̖̠͙̤̘̥̲̗ͅ   ̷̧͓̫͙͈̦̖̟̟̘̯͇͈̉ͪ̒ͪ̍́̏̌ͫ͗ͦ͂͒ͯ̊̆̍B̧͕̦̳͕̖̯͖͍̱͇̹͓̹̥̫ͫ͌ͯ͛̓͂̃̈ͦͦ̆ͤE̶̡ͯ̄̾̒̾ͣͧ̂̔̇̐̊ͥͨ̋̑̌ͦͮ͠͏̯̖̩͎͚͓̹͖̜̖̺̯̗̟̻͝S̸̶̮̮̥͈̲͔̘̦ͮ̎̑̉̂̾̀̚͢͝ͅT̵̘̩̥̣͉̩͚̭̺̮̘̠̳͖̳ͧ̄̔̋͋ͨ̔͂ͣ̊ͮ̍̊ͤͮ̋̽̚͝.




....


----------



## bingo88 (22. August 2012)

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

Ich habe da dein ecodedLength in Verdacht. Versuch mal bitte das hier:

```
if (count == 1)
{
    k = printf(...);
}
else
{
    k = printf(...);
}

encodedLength += k;
```
Zum Wegschreiben in den String:
Ich würde es nicht in den Eingabestring schreiben, sondern in einen neuen String. Dazu musst du innerhalb der Funktion dynamisch einen String mittels malloc erzeugen (später mit free wieder freigeben, sonst gibt es Speicherlöcher). Problematisch ist die Länge des Strings, die weißt du vorher nicht. Ich habe jetzt mal gesagt, neue Länge gleich alte Länge, da der kodierte String im schlimmsten Fall gleich dem Eingabestring ist (jeder Buchstabe kommt 1x vor, bspw. ABABABAB => ABABABAB). Das funktioniert nur, da du nicht 1A1B1A... schreibst (dann müsstest du neue Länge = 2x alte Länge sagen). Der neue String ist in der Regel eigentlich zu groß, aber du müsstest sonst erst die tatsächliche Länge bestimmen, den String mit dieser Länge erzeugen und dann noch einmal die eigentliche Kodierung durchführen. Oder halt einen Datentyp bauen, der sich dynamisch vergrößert, was allerdings jetzt dann doch Overkill wäre 


```
// Länge des Eingabestrings
int len = getLength(s);

// Speicher für Ausgabestring anlegen (Nullzeichen am Ende nicht vergessen, daher len + 1)
char *enc = (char*) malloc((len + 1) * sizeof(char));
int newlen = 0; // neue Länge

// String mit 0 initialisieren (für memset string.h includen oder halt selber schreiben)
memset(enc, '\0', (len + 1) * sizeof(char));

// ...

// beim Kodieren (in den Ausgabestring schreiben)
if (count == 1)
    k = sprintf((enc + newlen), "%c", s[i]);
else
    k = sprintf((enc + newlen), "%d%c", count, s[i]);

newlen += k;


// Kodierfunktion
// in: Zeiger auf den Eingabestring
// out: Zeiger auf den Zeiger für den Ausgabestring
// return: Länge des kodierten Strings
int rle_encode(const char *in, char **out)
{
    // ... siehe oben ...

    // Ausgabestring setzen
    *out = enc;

    return newlen;
}


// in der main

const char *s = "AAABBBBCCCCCCDDD";
int len;
char *enc;

// String kodieren, Ergebnis steht in enc
len = rle_encode(s, &enc);

// Ausgabe
printf("%d: %s\n", len, enc);

// Speicher freigeben
free(enc);
```
Sollte so in etwa funktionieren. Du musst evtl. noch ein paar Fehlerfälle abfangen (kein Speicher für malloc frei, NULL-Zeiger, etc.).


----------



## DarkMo (22. August 2012)

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


```
struct dynStr {
    char *s;
    void add(char *a) {
        char *tmp = malloc(genug speicher für s+a);
        tmp = s und a zusammen;
        this->s = tmp;
        free(tmp);
    }
};
```
könnt das was sein? jetzt auf die schnelle nur prototypisch/pseudocode aber ich hoffe, man erkennt was ich meine ><


----------



## bingo88 (22. August 2012)

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



DarkMo schrieb:


> ```
> struct dynStr {
> char *s;
> void add(char *a) {
> ...


 Ja, genau sowas in der Art meinte ich. Nur funktioniert das so in C nicht, da ein struct in C keine Methoden haben kann (geht nur in C++, da ein struct dort eigentlich ne Klasse mit public-by-default Zugriff ist).


----------



## DarkMo (22. August 2012)

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

ah ok, das das nur bei c++ so is wusst ich garnich ^^


----------



## boss3D (25. August 2012)

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

Hi all!

Sorry für die späte Rückmeldung. Bin gerade im Urlaub und habe nur mein iPad mit. Kann erst an Mi Abend wieder programmieren. Trotzdem schon mal danke für die Lösungsvorschläge. Diese sehen z.T. für mich als C Einsteiger doch etwas kompliziert aus; muss erst schauen, oh ich damit zusammenkomme ... 
_
PS: Die Kompression in einem neuen string zu speichern, wäre auch meine Idee gewesen, allerdings verbietet das die Angabe! Es darf im gesamten Beispiel nur mit *s gearbeitet werden. Deswegen muss ich auch meine Lsg. an diese strengen Vorgaben anpassen._


----------



## DarkMo (25. August 2012)

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

wurde doch auch nur mit char* gearbeitet ^^ nur weil die struktur dynStr heisst liegt da ja kein string dahinter ^^ oder was meintest du jetz genau? im endeffekt brauchst die strcut au ned (wenn das in der form c++ is) und bastelst einfach statt der struct methode ne globale funktion mit der selben aufgabe. hmm, zum bsp combineChars(&s, add) oder so ^^ oder s = combineChars(s, add). möglichkeiten gibts ja


----------



## boss3D (10. September 2012)

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

Weiteres Beispiel ...

Am Ende soll das Programm die Häufigkeit einzelner Buchstaben in einem Satz ermitteln und dieser soll der main übergeben werden. Außerdem soll die Anzahl aller Buchstaben gezählt werden. Mit Letzterem hätte ich einmal angefangen:

```
#include <stdio.h>

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

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

void count(char *s) {
    int i=0, counter=0, length=checkLength(s);

    while (i != length) {
        if (i >= 'A' && i <= 'Z') {
            counter=i-65;
        } 
        if (i >= 'a' && i <= 'z') {
            counter=i-97;
        }
        if (counter >= 0 && counter <= 25) {
            counter++;
        }
        i++;
    }

    printf("Character count: %d (100 %%)\n", counter);
}

/*int main(int argc, char *argv[]) {*/
int main(void) {
    /*char *s = argv[1];*/

    /*if (argc > 2) {
        printf("Invalid input!\n");
    }*/

    char *s = "Mal sehen was die Haeufigkeitsanalyse dieses Textes ergibt!? Ich denke, dass 'e' wohl wirklich der haeufigste Buchstabe sein wird!";
    count(s);

    return 0;
}
```
Wieso kommt der Code allerdings auf 26, statt 106?

_PS: Laut Angabe muss das übrigens so gemacht werden, dass man alles so umrechnet, bis man im Bereich von 0 - 25 angelangt ist. So soll das Programm angeblich leichter umzusetzen sein._


----------



## DarkMo (10. September 2012)

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

hmm, bei der count function sieht mir das ebbes schräg aus ^^

du gehst also den "string" zeichen für zeichen durch und versuchst herauszufinden, um welches zeichen es sich gerade handelt. dabei gehts dir nich um groß/klein schreibung, A und a sind das selbe. so, jetz speicherst du den "index" des buchstaben in counter (ascii-wert - ascii-wert von a -> a somit 0 und z = 25) um diesen index dann mit der anzahl zu überschrieben? ^^

also die anzahl der buchstaben im string ist ja dein lenght(s) - die kannste ja schonma ausgeben. da sollte dann die 106 rauskommen (sofern das die länge is). und bei dem rest... ich würde einfach nen int-array mit 27 elementen basteln, alle mit 0 initialisieren und je nach index des buchstaben das entsprechende element incrementieren. am ende dann nochma die ganze liste (äh array) durchgehn und alle buchstaben mit vorkommen >0 auflisten. alles was nich a-z is fällt als "sonderzeichen" ab und wird im letzten element gespeichert. da du die länge kennst, kannst du nun also auch ne prozentangabe ausgeben, zu wieviel prozent ein buchstabe im string vorhanden ist.

edit: leider nur teils grob gebastelt, aber so in etwa stell ichs mir vor

```
#include <stdio.h>

int ChrCount[27];

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

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

int count(char *s) {
    int i=0, chrIndex=0, length=checkLength(s);

    while (i != length) {
        if (s[i] >= 'A' && s[i] <= 'Z') {       // mit s[i] meine ich zugriff auf das zeichen von s an stelle i - hoffe das geht so überhaupt ><
            chrIndex = (int)s[i] - 65;          // joa, un dass soll bedeuten, dass der buchstabe in sein ascii-pendant umgewandelt wird ^^ - scheint sogar zu stimmen
        } else if (s[i] >= 'a' && s[i] <= 'z') {
            chrIndex = (int)s[i] - 97;
        } else {
            chrIndex = (int)s[i];
        }

        if (chrIndex >= 0 && chrIndex <= 25) {
            ChrCount[chrIndex]++;
        } else {
            ChrCount[26]++;
        }

        i++;
    }

    return length;
    //printf("Character count: %d (100 %%)\n", counter);
}

//int main(int argc, char *argv[]) {
int main(void) {
    //char *s = argv[1];

    /*if (argc > 2) {
        printf("Invalid input!\n");
    }*/

    // ChrCount-array initialisieren
    int i;
    for(i = 0; i < 27; i++) {
        ChrCount[i] = 0;
    }

    int lng;
    char *s = "Mal sehen was die Haeufigkeitsanalyse dieses Textes ergibt!? Ich denke, dass 'e' wohl wirklich der haeufigste Buchstabe sein wird!";
    lng = count(s);

    printf("Character count: %d (100 %%)\n", lng);
    float percent;
    for(i = 0; i < 27; i++) {
        if(ChrCount[i] > 0) {
            percent = 100 * ChrCount[i] / lng;
            printf("Character %c: %d times (%5.2f % of text)", i, ChrCount[i], percent);
        }
    }

    return 0;
}
```


----------



## boss3D (10. September 2012)

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

Als erstes will ich mal nur die richtige Anzahl an Buchstaben ausgegeben haben, den Rest überlege ich mir danach ...

Wenn ich einfach length ausgebe, wie du vorgeschlagen hast, dann käme 130 raus, was der Gesamtlänge (inkl. Sonderzeichen) entspricht. Das soll's ja auch nicht sein.


----------



## DarkMo (10. September 2012)

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

hab grad nochwas draneditiert ^^ du willst also also nur die anzahl der a/A-z/Z's haben? also bei "abc.." statt 5 ne 3? da ich in meinem bsp ja die anzahl der sonderzeichen in ChrCount[26] gespeichert hab, könntest du dann also ganz einfach lng-ChrCount[26] machen dafür.


----------



## boss3D (10. September 2012)

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



DarkMo schrieb:


> du willst also also nur die anzahl der a/A-z/Z's haben?


Ja, für's erste ...

Abgesehen davon, dass man deinen Code gar nicht debuggen kann, hätte ich das auch schon so ausprobiert, nur eben in der Pointer-Variante:

```
#include <stdio.h>

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

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

[COLOR=royalblue]void count(char *s) {
    int i=0, counter=0, length=checkLength(s);
 [COLOR=royalblue]     while (i != length) {
        if ([B]*(s+i)[/B] >= 'A' && [B]*(s+i)[/B] <= 'Z') {
            counter=[B](int)*(s+i)[/B]-65;
        } 
        if ([B]*(s+i)[/B] >= 'a' && [B]*(s+i)[/B] <= 'z') {
            counter=[B](int)*(s+i)[/B]-97;
        }
        if (counter >= 0 && counter <= 25) {
            counter++;
        }
        i++;
    }
 [COLOR=royalblue]     printf("Character count: %d (100 %%)\n", counter);
}
/*int main(int argc, char *argv[]) {*/
int main(void) {
    /*char *s = argv[1];*/

    /*if (argc > 2) {
        printf("Invalid input!\n");
    }*/

    char *s = "Mal sehen was die Haeufigkeitsanalyse dieses Textes ergibt!? Ich denke, dass 'e' wohl wirklich der haeufigste Buchstabe sein wird!";
    count(s);

    return 0;
}
```
Da kommt der Code dann aber nur auf 5 Buchstaben, statt 106 ...


----------



## DarkMo (10. September 2012)

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


```
if (counter >= 0 && counter <= 25) {
     counter++;
}
```
na das hier is doch genau der knackpunkt (meines erachtens nach) ^^ einmal schaust du mit counter, ob der aktuelle buchstabe ein a-z is um es kurz drauf mit der anzahl zu überschreiben. und diese anzahl überschreibst du dann im nächsten durchgang wieder mit dem ascii/index wert >< das kann doch nix werden ^^ der letzte "echte" buchstabe is das d, ascii wert von 100. die 97 abgezogen um auf den index zu kommen biste bei 3 und im anschluss setzte noch 1 druff -> 4. is jetz natürlich die frage, wieso er da ne 5 ausgibt *grübel*


----------



## boss3D (10. September 2012)

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

Ok, jetzt verstehe ich zumindest, was du meinst, nur was genau soll ich ändern? Bei dieser Variante käme ich wieder auf 130 ...

```
void count(char *s) {
    int i=0, [COLOR=royalblue]j=0, counter=0, length=checkLength(s);

    while (i != length) {
        if (*(s+i) >= 'A' && *(s+i) <= 'Z') {
            counter=((int)*(s+i))-65;
        } 
        if (*(s+i) >= 'a' && *(s+i) <= 'z') {
            counter=((int)*(s+i))-97;
        }
        if (counter >= 0 && counter <= 25) {
            [COLOR=royalblue]j++;        }
        i++;
    }

    printf("Character count: %d (100 %%)\n", [COLOR=royalblue]j);
}
```


----------



## DarkMo (10. September 2012)

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

baus mal wie ich mit der if-elseif-else schleife. im moment fragst du, ob es großbuchstaben sind oder kleinbuchstaben. in einem der beiden fälle gibst du counter dann den index des buchstabens - das funzt ja dann scheinbar gut jetz 

das problem is aber eben: wenn jetzt ein sonderzeichen auftaucht, behält counter einfach den wert vom vorangegangenen zeichen - und wird einfach mitgezählt. sollte es also weder ein groß- noch ein kleinbuchstabe sein, musst du einen wert für counter erzeugen, der ausserhalb von 0-25 liegt. also -1 oder 26 - oder 100 ^^ hautsache nix von 0-25. dann fällt das ganze in der nachfolgenden prüfung von counter nämlich durch und j wird nicht inkrementiert.

btw: du solltest j vllt in ascii oder irgendwas sinvolles umbenennen und dann diesen variablennamen dort verwenden, wo du grad counter nutzt und counter anstelle von j nutzen ^^ also der lesbarkeit wegen, für die funktionalität isses natürlich latte


----------



## boss3D (10. September 2012)

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

So funktioniert es jetzt:

```
void count(char *s) {
    int i=0, counter=0, ascii=0, length=checkLength(s);

    while (i != length) {
        if (*(s+i) >= 'A' && *(s+i) <= 'Z') {
            ascii=((int)*(s+i))-65;
        } else if (*(s+i) >= 'a' && *(s+i) <= 'z') {
            ascii=((int)*(s+i))-97;
        } else {
            ascii=((int)*(s+i)); /* Sonderzeichen */
        }
        if (ascii >= 0 && ascii <= 25) {
            counter++;
        }
        i++;
    }

    printf("Character count: %d (100 %%)\n", counter);
}
```
Many thanks!!!  

Jetzt überlege ich mir den Rest (und melde mich gegebenenfalls noch einmal) ...


----------



## boss3D (10. September 2012)

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

So, der Code wäre nahezu fertig, nur wie die Ausgabe zeigt, hat offensichtlich meine Berechnung der Vorkommnisse jedes Buchstaben noch einen Logikfehler ...

```
void analyzeString(char *s) {
    int i=0, j=0, counterOne=0, counterTwo=1, ascii=0, length=checkLength(s);
    double percentage=0.0;

    /* Anzahl der Buchstaben des Satzes ermitteln */
    while (i != length) {
        if (*(s+i) >= 'A' && *(s+i) <= 'Z') {
            ascii=((int)*(s+i))-65;
        } else if (*(s+i) >= 'a' && *(s+i) <= 'z') {
            ascii=((int)*(s+i))-97;
        } else {
            ascii=((int)*(s+i)); /* Sonderzeichen bekommen Werte außerhalb des Bereichs 0 - 25 */
        }
        if (ascii >= 0 && ascii <= 25) {
            counterOne++;
        }
        i++;
    }

    /* Anzahl der Vorkommnisse jedes Buchstaben ermitteln */
  [COLOR=royalblue]  for (i; i<length; i++) {
        for (j=1; j<length; j+=i) {
            if (*(s+i)==*(s+j)) {
                counterTwo++;
            } 
        }
    }
    printf("Character count: %d (100 %%)\n", counterOne);
    printf("\nDetailled Frequence Analysis:\n");
    printf("\n  : count : percentage\n======================\n");
    for (j='a'; j<='z'; j++) {
        percentage=(double)((counterTwo*100)/counterOne);
        printf("%c :     %d :       %.2lf\n", j, counterTwo, percentage);
    }
    putchar('\n');
}
```
Hier der gesamte Code:


Spoiler





```
#include <stdio.h>

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

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

void analyzeString(char *s) {
    int i=0, j=0, counterOne=0, counterTwo=1, ascii=0, length=checkLength(s);
    double percentage=0.0;

    /* Anzahl der Buchstaben des Satzes ermitteln */
    while (i != length) {
        if (*(s+i) >= 'A' && *(s+i) <= 'Z') {
            ascii=((int)*(s+i))-65;
        } else if (*(s+i) >= 'a' && *(s+i) <= 'z') {
            ascii=((int)*(s+i))-97;
        } else {
            ascii=((int)*(s+i)); /* Sonderzeichen bekommen Werte außerhalb des Bereichs 0 - 25 */
        }
        if (ascii >= 0 && ascii <= 25) {
            counterOne++;
        }
        i++;
    }

    /* Anzahl der Vorkommnisse jedes Buchstaben ermitteln */
    for (i; i<length; i++) {
        for (j=1; j<length; j+=i) {
            if (*(s+i)==*(s+j)) {
                counterTwo++;
            } 
        }
    }

    printf("Character count: %d (100 %%)\n", counterOne);
    printf("\nDetailled Frequence Analysis:\n");
    printf("\n  : count : percentage\n======================\n");
    for (j='a'; j<='z'; j++) {
        percentage=(double)((counterTwo*100)/counterOne);
        printf("%c :     %d :       %.2lf\n", j, counterTwo, percentage);
    }
    putchar('\n');
}

/*int main(int argc, char *argv[]) {*/
int main(void) {
    /*char *s = argv[1];*/

    /*if (argc > 2) {
        printf("Invalid input!\n");
    }*/

    char *s = "Mal sehen was die Haeufigkeitsanalyse dieses Textes ergibt!? Ich denke, dass 'e' wohl wirklich der haeufigste Buchstabe sein wird!";
    analyzeString(s);

    return 0;
}
```


----------



## DarkMo (10. September 2012)

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

erste frage: wieso beginnst du bei i=1 und nich 0? besonderer grund dazu? und bei der inneren for schleife haste for(j; ...) stehn ^^ da fehlt wohl auch was 

aso, ich glaube, ich verstehe, was du vorhast. du gehst jeden buchstaben durch und zählst dann, wieviele weitere davon vorkommen. an und für sich ok, nur hast du hier auch wieder einen counter (counterTwo) für alle möglichen buchstaben. zudem müsstest du alle vorkommen des aktuell betrachteten zeichens löschen und dann den length-wert anpassen und aufpassen, das dir das ned die forschleife irgendwie killt. ich finds etwas umständlich. warum machst dus nich einfach mit dem vorgeschlagenen array? einfach für jeden buchstaben ein array element + eines für sonderzeichen. dann kannste im ersten durchgang mit counterOne schon immer das array-element[ascii] inkrementieren un gut is. am ende haste dann ein volles array mit allen anzahlen und kannst das bequem auswerten (siehe mein erstes bsp).


----------



## boss3D (10. September 2012)

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

Anscheinend hast du gepostet, während ich noch editiert habe. Die derzeitig finale Version ist jetzt oben drinnen mit j=1. j sollte eigentlich größer sein als i, aber dass das so nicht funktionieren wird, ist mir jetzt klar. Für den ersten Buchstaben (a = 8 Vorkommnisse), würd's allerdings sogar funktionieren (mit counterTwo=0 und i=1). Nur müsste ich dem Konstrukt dann irgendwie sagen, dass es mit dem nächsten weitermachen soll ...

Werde mich jetzt mal in die Feld-Variante, die du vorgeschlagen hast, reindenken. Noch verstehe ich das nicht so ganz.


----------



## JimSim (10. September 2012)

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

Also jetzt mal ehrlich... überlegst du dir vorher was du da hinschreibst? Klingt jetzt vielleicht nen bisschen hart, aber die ersten Versionen deines Codes die du hier postest ergeben fast nie einen Sinn. Geh doch einfach mal logisch durch was da steht. Zeile für Zeile. Toll das DarkMo sich hier die Mühe macht und dir hilft und dir die Lösung präsentiert, aber das kann doch nicht Sinn und Zweck der Aufgabe sein.

Dennoch eine Anmerkungen: Warum ne neue for Schleife? Du gehst doch bereits alle Buchstaben des Strings vorher durch. Nutz das doch und verwende wie von DarkMo vorgeschlagen ein Array.

EDIT:
Bsp. Array[ascii] = Array[ascii]+1; Danach haste eine Array der für jeden Ascii Wert anzeigt wie viele da drin waren.


----------



## DarkMo (10. September 2012)

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

ich kanns ja versuchen zu erklären. sollta n sich nich sooo schwer sein *denk*

das array hat 27 elemente, also von 0 bis 26. der erste buchstabe hat also den index 0 -> array[0]. dieses element hat einen wert - hier sinnvollerweise nen integer zum zählen. anfangs sollte das natürlich auch 0 sein. also array[0] = 0; heisst soviel wie, dass vom ersten buchstaben 0 gezählt wurden. so, jetz gehst du ja den string da durch und reduzierst die gefundenen zeichen auf einen wert zwischen 0 und 25. 0-a, 1-b, 2-c... 25-z. und das kannst du ja perfekt für das array nutzen. den index jedes buchstabens hast du ja in der variable ascii gespeichert/rausgefunden. wenn du also ein a (oder A) findest, ist ascii immer 0 und in dem falle, kannst du array[<ascii von a>] -> ergo array[0] um eins erhöhen => array[0]++. hast also beim ersten fund aus dem wert dieses elements ne 1 gemacht (war ja mit 0 initialisiert). jeder weitere fund erhöht den entsprechenden wert.

kannste dann eben ganz einfach so lösen, dass du bei a/A-z/Z wie gehabt den ascii wert zurecht rechnest (wie bisher) und im letzten else teil (wo du grad einfach den unveränderten ascii wert speicherst) dann den ascii-wert auf 26 setzt. dann im anschluss erhöhst du einfach array[ascii] um eins und fertig. wie gesagt: ist was ein b, ist der ascii-wert 1 und somit wird array[ascii] - also array[1] um eins erhöht. ist es ein sonderzeichen, hat ascii den wert 26 und eben das letzte element wird um eins erhöht (z is die 25, danach is das einfache alphabet zuende). jo, un dann gehste das ganze array nochma durch und gibst alles aus. ob du da jetzt wie ich im bsp nur vorhandene zeichen ausgibst oder alle is ja dir überlassen. kannst das ganze auch, wie bei dir im letzten code, direkt in der count funktion machen. spart das zurück geben vom length wert und is sogar bissl eleganter *find* ^^

ich hoffe, das war einigermaßen verständlich erklärt ^^


----------



## boss3D (10. September 2012)

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



JimSim schrieb:


> Also jetzt mal ehrlich... überlegst du dir vorher was du da hinschreibst? Klingt jetzt vielleicht nen bisschen hart, aber die ersten Versionen deines Codes die du hier postest ergeben fast nie einen Sinn. Geh doch einfach mal logisch durch was da steht. Zeile für Zeile. Toll das DarkMo sich hier die Mühe macht und dir hilft und dir die Lösung präsentiert, aber das kann doch nicht Sinn und Zweck der Aufgabe sein.


Wie dir vielleicht aufgefallen ist, übernehme ich fast nichts von den Codes, die andere Leute hier posten, sondern versuche, aus deren Erklärungen das rauszuholen, was ich brauche, um eine eigene Version zu schreiben. Im Übrigen verstehe ich fast ein Drittel von dem, was DarkMo in seinem Code macht, nicht. Meinen eigenen hingegen kann ich zu 100 % nachvollziehen. Und einen funktionierenden Code zu schreiben, den man versteht, dürfte wohl der Sinn der Aufgabe sein ... 

Im Übrigen zählt Programmieren nun mal leider nicht zu meinen Stärken und ich würd's wohl freiwillig auch nicht machen, wenn ich es nicht für's Studium bräuchte. Reden wir mal über was, das ich gut kann und du nicht (da gibt's sicher genug). Mal sehen, wer dann mit solchen Sprüchen, wie dem deinigen oben kommt. 


JimSim schrieb:


> Dennoch eine Anmerkungen: Warum ne neue for Schleife? Du gehst doch bereits alle Buchstaben des Strings vorher durch. Nutz das doch [...]


Ich splitte am liebsten alles auf, das sich irgendwie trennen lässt, weil ich bei mehreren kleinen Konstrukten wesentlich leichter den Überblick behalte, aber ist natürlich eine Frage des persönlichen Programmierstils. 


JimSim schrieb:


> EDIT:
> Bsp. Array[ascii] = Array[ascii]+1; Danach haste eine Array der für jeden Ascii Wert anzeigt wie viele da drin waren.


Daran arbeite ich gerade ...

@ DarkMo
Danke für die Erklärung.


----------



## boss3D (10. September 2012)

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

Okay, wenn ich eure Variante mit dem Feld auch nur ansatzweise kapiert habe, sollte ich zumindest auf dem richtigen Weg sein ...

```
#include <stdio.h>

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

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

[COLOR=royalblue]void analyzeString(char *s) {
    int number[26], i=0, j=0, k=0, counter=0, ascii=0, length=checkLength(s);
    double percentage=0.0;

    /* Feld mit 0er initialisieren */
    for (i; i<=26; i++) {
        number[i]=0;
    }

    /* Anzahl der Buchstaben des Satzes ermitteln */
    while (i != length) {
        if (*(s+i) >= 'A' && *(s+i) <= 'Z') {
            ascii=((int)*(s+i))-65;
        } else if (*(s+i) >= 'a' && *(s+i) <= 'z') {
            ascii=((int)*(s+i))-97;
        } else {
            ascii=((int)*(s+i)); /* Sonderzeichen bekommen Werte außerhalb des Bereichs 0 - 25 */
            number[26]=ascii;
        }
        if (ascii >= 0 && ascii <= 25) {
            counter++;
            number[ascii]++;
        }
        i++;
    }

    printf("Character count: %d (100 %%)\n", counter);
    printf("\nDetailled Frequence Analysis:\n");
    printf("\n  : count : percentage\n======================\n");
    for (j='a', k; j<='z', k<=26; j++, k++) {
        percentage=(((double)number[k]*100)/(double)counter);
        printf("%c :     %d :       %.2lf\n", j, number[k], percentage);
    }
    putchar('\n');
}/*int main(int argc, char *argv[]) {*/
int main(void) {
    /*char *s = argv[1];*/

    /*if (argc > 2) {
        printf("Invalid input!\n");
    }*/

    char *s = "Mal sehen was die Haeufigkeitsanalyse dieses Textes ergibt!? Ich denke, dass 'e' wohl wirklich der haeufigste Buchstabe sein wird!";
    analyzeString(s);

    return 0;
}
```
Leider stimmen die Werte (noch) nicht und ich bekomme nach der Ausführung die Meldung: "Stack around the variable 'number' was corrupted!"


----------



## DarkMo (10. September 2012)

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

hmm, du musst 27 elemente bauen. das ist wie bei der länge von so zeichenketten. abc ist 3 lang, der index geht aber nur bis 2, da das erste element den index 0 hat (0 1 2 <- 3 elemente). für dein zähle array brauchst du also 26 elemente (für jeden buchstaben eins) und eines als "sammelbecken" für alle sonderzeichen - macht 27. und dann gibts zu beachten, dass bei number[27] das letzte element die 26 ist (wieder das bsp mit der länge von eben im kleinen: 3 länge, letzter index aber 2). du hast bei deinem number[26] in der for schleife bis <=26 gezählt - also die 26 inbegriffen (kleiner und gleich). also entweder brauchst du <=25 oder <26. mit den 27 elementen würde dein <=26 dann aber wieder anstandslos funktionieren.

und der zugriff auf das nicht vorhandene 27. element mit dem index 26 verursacht deinen fehler da ^^


----------



## boss3D (10. September 2012)

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

Ah, ok. Habe bei der Deklaration des Feldes den Index mit der Anzahl der Feldelementen verwechselt. Die Fehlermeldung ist jetzt weg, aber dafür stimmen in der Ausgabe gar keine Werte mehr; nicht einmal der Gesamtbuchstaben-Count ... 

^^ Genau deswegen will ich immer alles aufsplitten. Hast du nämlich ein großes Konstrukt und baust einen Fehler ein, ist alles im A****, auch das, was schon funktioniert hat.




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        

 


			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



Und was soll das eigentlich für eine komische Zeile nach der z-Zeile sein? Die habe ich nicht programmiert?! Die macht der selber.


Spoiler





```
#include <stdio.h>

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

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

[COLOR=royalblue]void analyzeString(char *s) {
    int charCount[27], i=0, j=0, k=0, counter=0, ascii=0, length=checkLength(s);
    float percentage=0.0;

    /* Feld mit 0er initialisieren */
    for (i; i<=26; i++) {
        charCount[i]=0;
    }

    /* Anzahl der Buchstaben des Satzes und deren Häufigkeit ermitteln */
    while (i != length) {
        if (*(s+i) >= 'A' && *(s+i) <= 'Z') {
            ascii=((int)*(s+i))-65;
        } else if (*(s+i) >= 'a' && *(s+i) <= 'z') {
            ascii=((int)*(s+i))-97;
        } else {
            ascii=((int)*(s+i)); /* Sonderzeichen bekommen Werte außerhalb des Bereichs 0 - 25 */
            charCount[26]=ascii;
        }
        if (ascii >= 0 && ascii <= 25) {
            counter++;
            charCount[ascii]++;
        }
        i++;
    }

    printf("Character count: %d (100 %%)\n", counter);
    printf("\nDetailled Frequence Analysis:\n");
    printf("\n  : count : percentage\n======================\n");
    for (j='a', k; j<='z', k<=26; j++, k++) {
        percentage=(((float)charCount[k]*100)/(float)counter);
        printf("%c :%6d :%11.2f\n", j, charCount[k], percentage);
    }
    putchar('\n');
}
/*int main(int argc, char *argv[]) {*/
int main(void) {
    /*char *s = argv[1];*/

    /*if (argc > 2) {
        printf("Invalid input!\n");
    }*/

    char *s = "Mal sehen was die Haeufigkeitsanalyse dieses Textes ergibt!? Ich denke, dass 'e' wohl wirklich der haeufigste Buchstabe sein wird!";
    analyzeString(s);

    return 0;
}
```



[Edit]
Ändert zwar eh nichts an der Ausgabe, aber müsste es im zweiten else nicht heißen: *charCount[26]++;* statt *charCount[26]=ascii;* ?


----------



## JimSim (10. September 2012)

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

Das Zeichen dahinter ist ein {, das nächste ascii Zeichen nach dem kleinen z. Und doch, das hast du so programmiert.  Denn k geht ja von 0 bis 26 bei dir, also umfasst 27 Zeichen anstatt der 26 notwendigen Zeichen. Änder mal auf k<=25...

EDIT:
Nach dem initialisieren des countChar-Arrays nicht vergessen i wieder auf 0 zu setzen...


----------



## boss3D (10. September 2012)

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

Aha, danke!

Das Problem ist jetzt nur noch, dass irgendwelche Buchstaben, die eigentlich vorhanden sind, entweder gar nicht mitgezählt werden, oder nur manchmal mitgezählt werden. Die Häufigkeiten sind jedenfalls überwiegend noch zu niedrig.

[Edit]
Ok, nach der Berücksichtigung deines Edits läuft's jetzt! Muchas gracias @ DarkMo & JimSim!!!


----------



## DarkMo (10. September 2012)

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

hehe, freut mich, wenn was klappt. hab mich eben auch tapfer "blind" durch mein ogl krams gebastelt. kA ob das funzt, seit 3 tagen hier un da bissl gewerkelt, ab un an mit nem bierchen drinne und dann hoffen, das alle rädchen ineinander greifen xD wenn man da dann das erste mal ausführen drückt, rechnet man schon mit 100 fehlern 

aber wegen aufsplitten usw: zum verständnis/debuggen is das ja kein problem. bei so kleinen programmen auch generell nich. aber prinzipiell hat jimsim da schon recht. du musst ja bedenken, dass die ausführungszeit dadurch prozentual ganz gut ansteigt. wenn du statt einer forschleife 2e vom selben format hast, dann verdoppelt sich ja die ausführungszeit - und 50% performanceverlust klingen schon nich mehr so toll  (also natürlich nur, wenn das ganze programm nur aus der einen oder 2 forschleifen besteht ^^). und auch wenns bei solchen programmen keinen unterschied macht, ob er nur10ms oder 20 brauch - so is ein grundsätzliches dran gewöhnen sicher nich verkehrt. wenn man später mal größeres zeugs baut, dann kann die erfahrung mit sowas im kleinen sicher auch helfen.

also: wenn man ein laufendes programm studiert und verbesserungspotential findet - einfach mal ausprobieren, ob mans nich noch nen bissl performanter "tunen" kann ^^


hmm, siehste, da kommt mir direkt nen bsp von meinem aktuellen projekt: ich lese nen mesh-file ein (also polygondaten usw von nem objekt) und versuche dann beim erstellen (also einma zum start) zu jedem polygon die nachbarn zu bestimmen. bei 1000en polygonen verschlingt das schon gut zeit. mein erster versuch hatte bei (lass mich lügen) ~1600 polygonen um die 30 sekunden gebraucht, mein zweiter ansatz ist jetzt bei 10-15 secs rum. aber selbst da hoffe ich, das noch verbessern zu können. weil ne halbe minute IST nerviger wie paar milisekunden ^^


----------



## JimSim (10. September 2012)

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

Und noch nen Tipp: Variablen die du in For-Schleifen verwendest immer in der Schleifenbedingung initialisieren... und nicht immer nur i nehmen. Das verwirrt. Es gibt auch noch andere Buchstaben im Alphabet, wie wir gerade durch zählen herausgefunden haben. 

Namen von Variablen/Klassen/überhaupt allem im Quellcode (was jetzt vielleicht nicht ein einfacher hochzähler in ner Schleife ist) sollten eindeutig sein. Das macht den Code zwar länger, aber wenn man nochmal drüber ließt, oder nen Fehler sucht, weiß man wenigstens was damit gemeint ist.
So wird dann aus counter bei dir bspw. ein "alleBuchstabenCounter" etc. dann vermeidest du auch leichter Fehler bei den du eine Variable für 2 unterschiedliche Dinge verwendest. Ich gebe zu, ich mach es auch nicht immer, aber es hat seine Vorteile, besonders wenn man nen Fehler sucht, und nicht weiß wo er steckt.

(Außer du programmierst Viren, dann sind Namen wie a, b, c, ... großartig  )



> Wie dir vielleicht aufgefallen ist, übernehme ich fast nichts von den Codes, die andere Leute hier posten, sondern versuche, aus deren Erklärungen das rauszuholen, was ich brauche, um eine eigene Version zu schreiben. Im Übrigen verstehe ich fast ein Drittel von dem, was DarkMo in seinem Code macht, nicht. Meinen eigenen hingegen kann ich zu 100 % nachvollziehen. Und einen funktionierenden Code zu schreiben, den man versteht, dürfte wohl der Sinn der Aufgabe sein ...



Durchaus löblich, ich will ja auch nur, das du verstehst was du machst, bevor du hier um Hilfe fragst. Das waren einfach Code-Stücke, die null Sinn gemacht haben. Das hättest du bemerken müssen wenn du einmal Zeile für Zeile deinen Code durchgegangen wärst und du dich gefragt hättest, was da nun genau passiert. Du hast doch schon einige Aufgaben gelöst und verstehst doch auch, was wir dir hier erklären. Da traue ich dir einfach zu, zu verstehen, was du selbst schreibst. Einfach ein wenig mehr Einsatz zeigen bevor du hier um Hilfe fragst. Ich helfe ja gerne, aber ich will wenigstens den Eindruck haben, das du dich vorher auch selbst ausgiebig damit beschäftigt hast.



> Im Übrigen zählt Programmieren nun mal leider nicht zu meinen Stärken und ich würd's wohl freiwillig auch nicht machen, wenn ich es nicht für's Studium bräuchte. Reden wir mal über was, das ich gut kann und du nicht (da gibt's sicher genug). Mal sehen, wer dann mit solchen Sprüchen, wie dem deinigen oben kommt.



Oh, ich bin mir sicher das es Dinge gibt, die du besser kannst als ich. Aber ich bitte hier auch nicht um Hilfe. Wie gesagt, ist das ja kein Problem und man hilft ja gerne. Aber ich glaub du kannst das mittlerweile einfach besser, als alle paar Zeilen deine eigenen Variablen zu überschreiben oder die Position im String mit ASCII-Werten zu vergleichen und sich dann zu wundern warum das nicht funktioniert. Da erwarte ich einfach mehr von dir, nach den Aufgaben, die du schon gelöst hast und ja auch verstehst.


----------



## boss3D (10. September 2012)

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

Eine kleine Anmerkung zu meiner Verteidigung: Uns ist im Unterricht immer eingetrichtert worden, möglichst speichersparend zu programmieren und mehrere (Zähl-)Variablen (für Schleifen) brauchen nun einmal mehr Platz, als eine, die immer wieder verwendet wird. Außerdem wollen die im Code selbst außnahmslos alles in Englisch haben (was mich ja nicht stört); nur Benutzeraufforderungen per printf dürfen auch in Deutsch sein. 

Jetzt im Nachhinein finde ich übrigens auch, dass das Beispiel leichter war, als gewisse andere, die wir hier schon behandelt haben. Und es gehört bereits zu den "schwersten" C-Beispielen, die ich für's Studium können muss. Zum Glück muss ich in meiner Richtung kein Top-Programmierer werden, aber ein allgemeines Verständnis in C und Java muss vorhanden sein ...

Bezüglich der Variablen-Namen: Im finalen Code habe ich das, denke ich, schon ganz gut gemacht mit den Benennungen?! Die für mich am schwersten verständlichen Passagen habe ich noch dazu kommentiert, falls ich mir den Code in ein paar Wochen wieder anschaue.


Spoiler





```
#include <stdio.h>

int [COLOR=royalblue]checkLength(char *s) {
    int length=0;

    while (*(s+[COLOR=royalblue]length) != '\0') {
        [COLOR=royalblue]length++;
    }
    return [COLOR=royalblue]length;
}

void [COLOR=royalblue]analyzeString(char *s) {
    int [COLOR=royalblue]charCount[27], i=0, j=0, k=0, [COLOR=royalblue]counter=0, [COLOR=royalblue]ascii=0, [COLOR=royalblue]length=[COLOR=royalblue]checkLength(s);
    float [COLOR=royalblue]percentage=0.0;

    /* Feld mit 0er initialisieren */
    for (i; i<=26; i++) {
        [COLOR=royalblue]charCount[i]=0;
    }

    i=0;

    /* Anzahl der Buchstaben des Satzes und deren Häufigkeit ermitteln */
    while (i != [COLOR=royalblue]length) {
        if (*(s+i) >= 'A' && *(s+i) <= 'Z') {
           [COLOR=royalblue] ascii=((int)*(s+i))-65;
        } else if (*(s+i) >= 'a' && *(s+i) <= 'z') {
           [COLOR=royalblue] ascii=((int)*(s+i))-97;
        } else {
            [COLOR=royalblue]ascii=((int)*(s+i)); /* Sonderzeichen haben Werte außerhalb des Bereichs 0 - 25 */
            [COLOR=royalblue]charCount[26]++; /* für jedes Sonderzeichen wird Wert im letzten Feldelement inkrementiert */
        }
        if ([COLOR=royalblue]ascii >= 0 && [COLOR=royalblue]ascii <= 25) {
           [COLOR=royalblue] counter++;
            [COLOR=royalblue]charCount[[COLOR=royalblue]ascii]++; /* Wert an der Stelle des Feldindex des jeweiligen Buchstaben wird bei Vorkommen inkrementiert */
        }
        i++;
    }

    printf("Character count: %d (100 %%)\n", [COLOR=royalblue]counter);
    printf("\nDetailled Frequence Analysis:\n");
    printf("\n  : count : percentage\n======================\n");
    for (j='a', k; j<='z', k<=25; j++, k++) {
        [COLOR=royalblue]percentage=(((float)[COLOR=royalblue]charCount[k]*100)/(float)[COLOR=royalblue]counter);
        printf("%c :%6d :%11.2f\n", j, [COLOR=royalblue]charCount[k], [COLOR=royalblue]percentage);
    }
    putchar('\n');
}

int main(int argc, char *argv[]) {
    char *s = argv[1];

    if (argc = 1) {
        printf("Invalid input! Missing parameter.\n");
    } else if (argc > 2) {
        printf("Invalid input! Too many parameters.\n");
    }

    [COLOR=royalblue]analyzeString(s);

    return 0;
}
```


----------



## JimSim (11. September 2012)

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

Dein Lehrer ist schon etwas älteres Semester, oder? 
Naja, ganz unrecht hat er ja nicht. Du kannst dich durchaus darauf festlegen, das Zähler für Schleifen immer gleich heißen. So oder so solltest du sie aber auch erst in der Schleife initialisieren. (oder sogar definieren, dann kann nach Ablauf der Schleife der Garbage-Collector aufräumen). D.h. nicht for (i, i<...) sondern for (i=0, i<...)

Aber ehrlich gesagt, ist jetzt der Platz, den so ne Variable einnimmt, nicht wild. (Kommt natürlich drauf an worauf du programmierst, auf Maschinen bzw. Automaten mag das noch anders sein) Es gibt halt beim programmieren unterschiedliche Philosophien. "State of the Art" ist es momentan eigentlich, wenn man praktisch keine Kommentare mehr benötigt, sondern sich alles durch die Benennung der Variablen, Klassen und Methoden erklärt. Das ist manchmal allerdings auch ******* kompliziert und aufwendig. Wirklich treffende Namen zu finden, ist nicht immer leicht. Und bei sehr technischen Angelegenheiten, kommt man um Kommentare leider manchmal nicht rum. Welche Sprache das ganze ist... Naja, wenn man das ganze OpenSource macht, ist es natürlich unter dem oben genannten Ansatz löblich wenn alles in Englisch ist, damits auch jeder versteht. Ansonsten aber auch einfach persönliche Präferenz.

Was die Benennung in deinem Beispiel betrifft... Naja, man kann natürlich immer noch präziser werden. In nem größeren Projekt, würde mir das nicht ausreichen. Aber das passt hier für schon. Man muss ja nicht päpstlicher sein, als der Papst.  Ist ja jetzt erstmal nur für dich, und so lange du weißt was was ist, ist ja alles okay.


----------



## bingo88 (11. September 2012)

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

Naja, in C gibt es keinen Garbage Collector  Außerdem je nach verwendetem C-Standard muss man die Variablen im voraus deklarieren. Ich meine, für for (int i = 0; ...) benötigt man mindestens den C99 Standard.


----------



## JimSim (11. September 2012)

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

Ja gut... eh... ich meinte in Java. 
Ja, sorry. C programmier ich eigentlich nicht, da vergisst man solche Kleinigkeiten gerne mal, wobei das mit dem Garbage Collector weiß ich eigentlich... Naja, wurscht. Gibt ja genug schlaue Köpfe hier die mich korrigieren können.


----------



## boss3D (13. Oktober 2012)

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

Habe heute mal zum Spaß TIC TAC TOE programmiert ... 

Bis auf eine (entscheidende ) Kleinigkeit funktioniert das Programm auch schon sehr gut:


Spoiler





```
#include <stdio.h>
#include <time.h>

#define ROWS 3
#define COLUMNS 3

int checkWinner(int matrix[][COLUMNS], int rows) { 
    if (matrix[0][0]==79 && matrix[0][1]==79 && matrix[0][2]==79) {
        return 0;
    } else if (matrix[1][0]==79 && matrix[1][1]==79 && matrix[1][2]==79) {
        return 0;
    } else if (matrix[2][0]==79 && matrix[2][1]==79 && matrix[2][2]==79) {
        return 0;
    } else if (matrix[0][0]==79 && matrix[1][0]==79 && matrix[2][0]==79) {
        return 0;
    } else if (matrix[0][1]==79 && matrix[1][1]==79 && matrix[2][1]==79) {
        return 0;
    } else if (matrix[0][2]==79 && matrix[1][2]==79 && matrix[2][2]==79) {
        return 0;
    } else if (matrix[0][0]==79 && matrix[1][1]==79 && matrix[2][2]==79) {
        return 0;
    } else if (matrix[0][2]==79 && matrix[1][1]==79 && matrix[2][0]==79) {
        return 0;
    } else if (matrix[0][0]==88 && matrix[0][1]==88 && matrix[0][2]==88) {
        return 0;
    } else if (matrix[1][0]==88 && matrix[1][1]==88 && matrix[1][2]==88) {
        return 0;
    } else if (matrix[2][0]==88 && matrix[2][1]==88 && matrix[2][2]==88) {
        return 0;
    } else if (matrix[0][0]==88 && matrix[1][0]==88 && matrix[2][0]==88) {
        return 0;
    } else if (matrix[0][1]==88 && matrix[1][1]==88 && matrix[2][1]==88) {
        return 0;
    } else if (matrix[0][2]==88 && matrix[1][2]==88 && matrix[2][2]==88) {
        return 0;
    } else if (matrix[0][0]==88 && matrix[1][1]==88 && matrix[2][2]==88) {
        return 0;
    } else if (matrix[0][2]==88 && matrix[1][1]==88 && matrix[2][0]==88) {
        return 0;
    } else {
        return 1;
    }
}

void playerOne() {
    int x1=0, y1=0, error=0;
    int matrix[ROWS][COLUMNS] = { 0 };

    printf("Player 1, it's your turn. Please enter coordinates: ");
    scanf("%d %d", &x1, &y1);
    if ((x1 <= 0 || x1 > 3) || (y1 <= 0 || y1 > 3)) { [COLOR=seagreen]/* if Player 1's input is invalid, ask again */        printf("\nINVALID INPUT! Try again ...\n\n");
        playerOne();
        error=1;
    } else if (matrix[x1][y1]==79 || matrix[x1][y1]==88) { [COLOR=seagreen]/* if Player 1 chooses a field that is already taken, ask again */        printf("\nField already taken! Try again ...\n\n");
        playerOne();
        error=2;
    }

    if (error != 1 && error != 2) { [COLOR=seagreen]/* only print matrix if user input is valid */        matrix[x1-1][y1-1]=88; [COLOR=seagreen]/* ASCII value for 'X' */        [COLOR=royalblue][B]matrix[ROWS][COLUMNS]=printMatrix(matrix, ROWS);[/B] [COLOR=seagreen]/* save the result of each round in matrix */        if (checkWinner(matrix, ROWS)==0) {
            printf("Congratulations, Player 1! You won the game.\n");
        }
    }
}

void playerTwo() {
    int x2=0, y2=0, error=0;
    int matrix[ROWS][COLUMNS] = { 0 };

    printf("Player 2, it's your turn. Please enter coordinates: ");
    scanf("%d %d", &x2, &y2);
    if ((x2 <= 0 || x2 > 3) || (y2 <= 0 || y2 > 3)) { [COLOR=seagreen]/* if Player 2's input is invalid, ask again */        printf("\nINVALID INPUT! Try again ...\n\n");
        playerTwo();
        error=1;
    } else if (matrix[x2][y2]==79 || matrix[x2][y2]==88) { [COLOR=seagreen]/* if Player 2 chooses a field that is already taken, ask again */        printf("\nField already taken! Try again ...\n\n");
        playerTwo();
        error=2;
    }

    if (error != 1 && error != 2) { [COLOR=seagreen]/* only print matrix if user input is valid */        matrix[x2-1][y2-1]=79; [COLOR=seagreen]/* ASCII value for 'O' */       [COLOR=royalblue][B] matrix[ROWS][COLUMNS]=printMatrix(matrix, ROWS);[/B] [COLOR=seagreen]/* save the result of each round in matrix */        if (checkWinner(matrix, ROWS)==0) {
            printf("Congratulations, Player 2! You won the game.\n");
        }
    }
}

int printMatrix(int matrix[][COLUMNS], int rows) {
    int i=0, j=0;
    int resultMatrix[ROWS][COLUMNS] = { 0 };

    printf("\n");
    for (i=0; i<rows; i++) {
        for (j=0; j<COLUMNS; j++) {
            if (matrix[i][j] == 88 || matrix[i][j] == 79) {
                (j<2) ? (printf(" %c |", matrix[i][j])) : (printf(" %c", matrix[i][j]));
            } else {
                (j<2) ? (printf("   |", matrix[i][j])) : (printf("", matrix[i][j]));
            }
            [COLOR=royalblue][B]resultMatrix[i][j]=matrix[i][j];[/B]        }
        printf(i<2 ? "\n---+---+---\n" : "");
     }
     printf("\n\n");

     [COLOR=royalblue][B]return resultMatrix[i][j];[/B]}

int main(void) {
    int i=0;
    int matrix[ROWS][COLUMNS] = { 0 };
    double time1=0.0, tstart;

    tstart=clock();
    
    printf("TIC TAC TOE\n");
    printMatrix(matrix, ROWS);
    printf("Player 1 ... X\nPlayer 2 ... O\n\n");

    while (checkWinner(matrix, ROWS)!=0) { [COLOR=seagreen]/* continue game until one player has won ... */        playerOne();
        playerTwo();
    }

    while (i<9) { [COLOR=seagreen]/* ... or the game ends in a tie */        checkWinner(matrix, ROWS);
        if (i==8 && checkWinner(matrix, ROWS)!=0) {
            printf("Oops, the game ended in a tie!\n");
        }
        i++;
    }

    time1+=clock()-tstart;
    time1=time1/CLOCKS_PER_SEC;

    printf("\nThe game lasted %.2f minutes.\n\n", time1/60);

    return 0;
}
```



Das Problem ist, dass sich das Programm nicht den Zustand der Matrix aus der vorigen Runde merkt. Deswegen kommt das Spiel leider nie zu einem Ende. Den Fehler vermute ich in einer bzw. zwei der markierten Zeilen, aber ich komme einfach nicht darauf.

Ich hätte mir das jedenfalls so vorgestellt, dass das Ergebnis jeder Runde von printMatrix, der Funktion, die für die Ausgabe des aktuellen Zustands zuständig ist, in resultMatrix gespeichert wird. Ab der zweiten Runde sollten dann beide Spieler nur noch den Inhalt der resultMatrix verwenden und da ihre neuen Werte hinzufügen, falls die entsprechenden Felder noch frei sind ...


----------



## boss3D (14. Oktober 2012)

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

Sorry für DP, habe aber Neuigkeiten ...

Ich konnte zwar das Problem aus dem vorigen Posting nicht lösen, habe aber einen Weg herum gefunden. Jetzt fragen nicht mehr die beiden Spieler den Status der jeweiligen Runde ab, sondern eine eigene Funktion checkStatus überprüft diesen. Dadurch funktioniert mein TIC TAC TOE jetzt endlich! 

Dafür habe ich zwei neue, aber kleinere Probleme, die leichter zu lösen sein sollten:

1.) In der Funktion checkStatus funktioniert die Abfrage, ob das Spiel unentschieden ausging, offenbar nicht richtig. Der Unentschieden-Zustand wird nicht erkannt und das Spiel erwartet auch bei bereits vollem Spielfeld weiter Benutzereingaben.  
Ich habe mir gedacht, ich frage einfach ab, ob bereits alle Felder der Matrix mit 79 oder 88 belegt sind, aber so geht's anscheindend nicht ...

2.) Das Bisschen Code, das in der main nach der while Schleife steht (Zeitmessung), wird aus irgendeinem Grund nicht berücksichtigt bzw. nicht ausgeführt.  

Hier der aktuelle Code:


Spoiler





```
#include <stdio.h>
#include <time.h>

#define ROWS 3
#define COLUMNS 3

int checkWinner(int matrix[][COLUMNS], int rows) { 
    if (matrix[0][0]==79 && matrix[0][1]==79 && matrix[0][2]==79) {
        return 0;
    } else if (matrix[1][0]==79 && matrix[1][1]==79 && matrix[1][2]==79) {
        return 0;
    } else if (matrix[2][0]==79 && matrix[2][1]==79 && matrix[2][2]==79) {
        return 0;
    } else if (matrix[0][0]==79 && matrix[1][0]==79 && matrix[2][0]==79) {
        return 0;
    } else if (matrix[0][1]==79 && matrix[1][1]==79 && matrix[2][1]==79) {
        return 0;
    } else if (matrix[0][2]==79 && matrix[1][2]==79 && matrix[2][2]==79) {
        return 0;
    } else if (matrix[0][0]==79 && matrix[1][1]==79 && matrix[2][2]==79) {
        return 0;
    } else if (matrix[0][2]==79 && matrix[1][1]==79 && matrix[2][0]==79) {
        return 0;
    } else if (matrix[0][0]==88 && matrix[0][1]==88 && matrix[0][2]==88) {
        return 0;
    } else if (matrix[1][0]==88 && matrix[1][1]==88 && matrix[1][2]==88) {
        return 0;
    } else if (matrix[2][0]==88 && matrix[2][1]==88 && matrix[2][2]==88) {
        return 0;
    } else if (matrix[0][0]==88 && matrix[1][0]==88 && matrix[2][0]==88) {
        return 0;
    } else if (matrix[0][1]==88 && matrix[1][1]==88 && matrix[2][1]==88) {
        return 0;
    } else if (matrix[0][2]==88 && matrix[1][2]==88 && matrix[2][2]==88) {
        return 0;
    } else if (matrix[0][0]==88 && matrix[1][1]==88 && matrix[2][2]==88) {
        return 0;
    } else if (matrix[0][2]==88 && matrix[1][1]==88 && matrix[2][0]==88) {
        return 0;
    } else {
        return 1;
    }
}

void checkStatus() { [COLOR=seagreen]/* check status of the game after each round */    int i=0, j=0;
    int matrix[ROWS][COLUMNS] = { 0 };
    int newMatrix[ROWS][COLUMNS]= { 0 };

    newMatrix[ROWS][COLUMNS]=printMatrix(matrix, ROWS);

    while (checkWinner(newMatrix, ROWS)!=0) { [COLOR=seagreen]/* continue the game until one player has won ... */        playerOne(newMatrix, ROWS);
        playerTwo(newMatrix, ROWS);
    }

    [COLOR=royalblue][B]for (i=0; i<ROWS; i++) {[/B] [COLOR=seagreen]/* ... or the game has ended in a tie */       [B][COLOR=royalblue] for (j=0; i<COLUMNS; j++) {
            if (newMatrix[i][j]==79 || newMatrix[i][j]==88) {
                printf("Oops, the game ended in a tie!\n");
            }
        }
    }  [/B]
}

int playerOne(int matrix[][COLUMNS], int rows) {
    int x1=0, y1=0, error=0;

    printf("Player 1, it's your turn. Please enter coordinates: ");
    scanf("%d %d", &x1, &y1);
    putchar('\n');
    if ((x1 <= 0 || x1 > 3) || (y1 <= 0 || y1 > 3)) { [COLOR=seagreen]/* if Player 1's input is invalid, ask again */        printf("\nINVALID INPUT! Try again ...\n\n");
        playerOne(matrix, ROWS);
        error=1;
    } else if (matrix[x1-1][y1-1]==79 || matrix[x1-1][y1-1]==88) { [COLOR=seagreen]/* if Player 1 chooses a field that is already taken, ask again */        printf("Field already taken! Try again ...\n\n");
        playerOne(matrix, ROWS);
        error=2;
    }

    if (error != 1 && error != 2) { [COLOR=seagreen]/* only print matrix if user input is valid */        matrix[x1-1][y1-1]=88; [COLOR=seagreen]/* ASCII value for 'X' */        printMatrix(matrix, ROWS);
        if (checkWinner(matrix, ROWS)==0) {
            printf("Congratulations, Player 1! You won the game.\n\n");
        }
    }
    return matrix[ROWS][COLUMNS];
}

int playerTwo(int matrix[][COLUMNS], int rows) {
    int x2=0, y2=0, error=0;

    printf("Player 2, it's your turn. Please enter coordinates: ");
    scanf("%d %d", &x2, &y2);
    putchar('\n');
    if ((x2 <= 0 || x2 > 3) || (y2 <= 0 || y2 > 3)) { [COLOR=seagreen]/* if Player 2's input is invalid, ask again */        printf("\nINVALID INPUT! Try again ...\n\n");
        playerTwo(matrix, ROWS);
        error=1;
    } else if (matrix[x2-1][y2-1]==79 || matrix[x2-1][y2-1]==88) { [COLOR=seagreen]/* if Player 2 chooses a field that is already taken, ask again */        printf("Field already taken! Try again ...\n\n");
        playerTwo(matrix, ROWS);
        error=2;
    }

    if (error != 1 && error != 2) { [COLOR=seagreen]/* only print matrix if user input is valid */        matrix[x2-1][y2-1]=79; [COLOR=seagreen]/* ASCII value for 'O' */        printMatrix(matrix, ROWS);
        if (checkWinner(matrix, ROWS)==0) {
            printf("Congratulations, Player 2! You won the game.\n\n");
        }
    }
    return matrix[ROWS][COLUMNS];
}

int printMatrix(int matrix[][COLUMNS], int rows) {
    int i=0, j=0;
    int resultMatrix[ROWS][COLUMNS] = { 0 };

    for (i=0; i<rows; i++) {
        for (j=0; j<COLUMNS; j++) {
            if (matrix[i][j] == 88 || matrix[i][j] == 79) {
                (j<2) ? (printf(" %c |", matrix[i][j])) : (printf(" %c", matrix[i][j]));
            } else {
                (j<2) ? (printf("   |", matrix[i][j])) : (printf("", matrix[i][j]));
            }
            resultMatrix[i][j]=matrix[i][j];
        }
        printf(i<2 ? "\n---+---+---\n" : "");
     }
     printf("\n\n");

     return resultMatrix[i][j];
}

int main(void) {
    int i=0;
    int matrix[ROWS][COLUMNS] = { 0 };
    double time1=0.0, time2=0.0;

    time1=clock();

    printf("TIC TAC TOE\n\n");
    printf("Player 1 ... X\nPlayer 2 ... O\n\n");

    [B][COLOR=red]while (checkWinner(matrix, ROWS)!=0) {[/B] [COLOR=seagreen]/* continue checking status of the game until it ends one way or another */        checkStatus();
    }

    [B][COLOR=royalblue]time2=clock()-time1;
     time2=time2/CLOCKS_PER_SEC;
 [COLOR=royalblue]      printf("\nThe game lasted %.2lf minutes.\n\n", time2/60);[/B]

    return 0;
}
```



*[EDIT]*
Habe jetzt eine neue Version, in der die Überprüfung, ob ein Unentschieden erreicht wurde, von einer eigenen Funktion übernommen wird. Hier allerdings das Problem: Die Funktion meint, schon nach jeweils einer User-Eingabe, also zwei (von insg. neun) belegten Matrix-Feldern, dass es ein Unentschieden gäbe ...

Vielleicht ist es in dieser Variante aber leichter für euch, zu durchschauen, was ich machen möchte, und mir zu helfen. 


Spoiler





```
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define ROWS 3
#define COLUMNS 3

int checkWinner(int matrix[][COLUMNS], int rows) { [COLOR=seagreen]/* all possible ways to win the game */    if (matrix[0][0]==79 && matrix[0][1]==79 && matrix[0][2]==79) {
        return 0;
    } else if (matrix[1][0]==79 && matrix[1][1]==79 && matrix[1][2]==79) {
        return 0;
    } else if (matrix[2][0]==79 && matrix[2][1]==79 && matrix[2][2]==79) {
        return 0;
    } else if (matrix[0][0]==79 && matrix[1][0]==79 && matrix[2][0]==79) {
        return 0;
    } else if (matrix[0][1]==79 && matrix[1][1]==79 && matrix[2][1]==79) {
        return 0;
    } else if (matrix[0][2]==79 && matrix[1][2]==79 && matrix[2][2]==79) {
        return 0;
    } else if (matrix[0][0]==79 && matrix[1][1]==79 && matrix[2][2]==79) {
        return 0;
    } else if (matrix[0][2]==79 && matrix[1][1]==79 && matrix[2][0]==79) {
        return 0;
    } else if (matrix[0][0]==88 && matrix[0][1]==88 && matrix[0][2]==88) {
        return 0;
    } else if (matrix[1][0]==88 && matrix[1][1]==88 && matrix[1][2]==88) {
        return 0;
    } else if (matrix[2][0]==88 && matrix[2][1]==88 && matrix[2][2]==88) {
        return 0;
    } else if (matrix[0][0]==88 && matrix[1][0]==88 && matrix[2][0]==88) {
        return 0;
    } else if (matrix[0][1]==88 && matrix[1][1]==88 && matrix[2][1]==88) {
        return 0;
    } else if (matrix[0][2]==88 && matrix[1][2]==88 && matrix[2][2]==88) {
        return 0;
    } else if (matrix[0][0]==88 && matrix[1][1]==88 && matrix[2][2]==88) {
        return 0;
    } else if (matrix[0][2]==88 && matrix[1][1]==88 && matrix[2][0]==88) {
        return 0;
    } else {
        return 1;
    }
}

[COLOR=royalblue][B]void checkTie(int matrix[][COLUMNS], int rows) { [/B][COLOR=seagreen]/* check if the game ended in a tie */[B]
    int i=0, j=0;
    
    for (i=0; i<ROWS; i++) {
        for (j=0; j<COLUMNS; j++) {
            if (matrix[i][j]==79 || matrix[i][j]==88) {
                printf("Oops, the game ended in a tie!\n\n");
                exit(0);
            }
        }
    }
}[/B]
void checkStatus() { [COLOR=seagreen]/* check status of the game after each round */    int i=0, j=0, k=0;
    int matrix[ROWS][COLUMNS] = { 0 };
    int newMatrix[ROWS][COLUMNS]= { 0 };

    newMatrix[ROWS][COLUMNS]=printMatrix(matrix, ROWS);

    while (checkWinner(newMatrix, ROWS)!=0) { [COLOR=seagreen]/* continue the game until one player has won ... */        playerOne(newMatrix, ROWS);
        playerTwo(newMatrix, ROWS);
        [COLOR=royalblue][B]checkTie(newMatrix, ROWS);[/B] [COLOR=seagreen]/* ... or the game ends in a tie */    }
}

int playerOne(int matrix[][COLUMNS], int rows) {
    int x1=0, y1=0, error=0;

    printf("Player 1, it's your turn. Please enter coordinates: ");
    scanf("%d %d", &x1, &y1);
    putchar('\n');
    if ((x1 <= 0 || x1 > 3) || (y1 <= 0 || y1 > 3)) { [COLOR=seagreen]/* if Player 1's input is invalid, ask again */        printf("\nINVALID INPUT! Try again ...\n\n");
        playerOne(matrix, ROWS);
        error=1;
    } else if (matrix[x1-1][y1-1]==79 || matrix[x1-1][y1-1]==88) { [COLOR=seagreen]/* if Player 1 chooses a field that is already taken, ask again */        printf("Field already taken! Try again ...\n\n");
        playerOne(matrix, ROWS);
        error=2;
    }

    if (error != 1 && error != 2) { [COLOR=seagreen]/* only print matrix if user input is valid */        matrix[x1-1][y1-1]=88; [COLOR=seagreen]/* ASCII value for 'X' */        printMatrix(matrix, ROWS);
        if (checkWinner(matrix, ROWS)==0) {
            printf("Congratulations, Player 1! You won the game.\n\n");
        } 
    }
    return matrix[ROWS][COLUMNS];
}

int playerTwo(int matrix[][COLUMNS], int rows) {
    int x2=0, y2=0, error=0;

    printf("Player 2, it's your turn. Please enter coordinates: ");
    scanf("%d %d", &x2, &y2);
    putchar('\n');
    if ((x2 <= 0 || x2 > 3) || (y2 <= 0 || y2 > 3)) { [COLOR=seagreen]/* if Player 2's input is invalid, ask again */        printf("\nINVALID INPUT! Try again ...\n\n");
        playerTwo(matrix, ROWS);
        error=1;
    } else if (matrix[x2-1][y2-1]==79 || matrix[x2-1][y2-1]==88) { [COLOR=seagreen]/* if Player 2 chooses a field that is already taken, ask again */        printf("Field already taken! Try again ...\n\n");
        playerTwo(matrix, ROWS);
        error=2;
    }

    if (error != 1 && error != 2) { [COLOR=seagreen]/* only print matrix if user input is valid */        matrix[x2-1][y2-1]=79; [COLOR=seagreen]/* ASCII value for 'O' */        printMatrix(matrix, ROWS);
        if (checkWinner(matrix, ROWS)==0) {
            printf("Congratulations, Player 2! You won the game.\n\n");
        } 
    }
    return matrix[ROWS][COLUMNS];
}

int printMatrix(int matrix[][COLUMNS], int rows) {
    int i=0, j=0;
    int resultMatrix[ROWS][COLUMNS] = { 0 };

    for (i=0; i<ROWS; i++) {
        for (j=0; j<COLUMNS; j++) {
            if (matrix[i][j] == 88 || matrix[i][j] == 79) {
                (j<2) ? (printf(" %c |", matrix[i][j])) : (printf(" %c", matrix[i][j]));
            } else {
                (j<2) ? (printf("   |", matrix[i][j])) : (printf("", matrix[i][j]));
            }
            resultMatrix[i][j]=matrix[i][j];
        }
        printf(i<2 ? "\n---+---+---\n" : "");
     }
     printf("\n\n");

     return resultMatrix[i][j];
}

int main(void) {
    int i=0;
    int matrix[ROWS][COLUMNS] = { 0 };
    double time1=0.0, time2=0.0;

    time1=clock();

    printf("TIC TAC TOE\n\n");
    printf("Player 1 ... X\nPlayer 2 ... O\n\n");

    while (checkWinner(matrix, ROWS)!=0) { [COLOR=seagreen]/* continue checking status of the game until it ends one way or another */        checkStatus();
    }

    time2=clock()-time1;
    time2=time2/CLOCKS_PER_SEC;

    printf("\nThe game lasted %.2lf minutes.\n\n", time2/60);

    return 0;
}
```


----------



## Freddycbv (15. Oktober 2012)

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

hab das ganze nur mal kurz überflogen, und 2 größere Schwachstellen in der Logik gefunden:
1. Position des Aufrufes von checkTie();

```
while (checkWinner(newMatrix, ROWS)!=0) 
{ [COLOR=seagreen]/* continue the game until one player has won ... */         
     playerOne(newMatrix, ROWS);        
     playerTwo(newMatrix, ROWS);         
     [COLOR=royalblue][B]checkTie(newMatrix, ROWS);[/B] [COLOR=seagreen]/* ... or the game ends in a tie */    
}
```
PlayerOne setzt einen Stein, dann PlayerTwo. Unentschieden gibts ja, wenn das Spielbrett voll ist, also nach 9 Zügen( = 9 belegte Felder):
Also folgende Reihenfolge: Zug1: PlayerOne; Zug2: PlayerTwo; Zug3: PlayerOne ... 
Wenn du das durchspielst, kommst du drauf, dass Spieler1 den letzten Zug macht, also das Unentschieden nach dem letzten Zug von PlayerOne und vor dem (5.) Zug von PlayerTwo festliegt. checkTie() muss also zwischen playerone() und playertwo()

2. Die funktion checkTie()

```
[B]void checkTie(int matrix[][COLUMNS], int rows) 
{ [/B]/* check if the game ended in a tie */[B]    
     int i=0, j=0;         
[COLOR=darkred]     for (i=0; i<ROWS; i++) {        
         for (j=0; j<COLUMNS; j++) {            
             if ([COLOR=navy]matrix[[COLOR=darkred]i][[COLOR=darkred]j]==79 || matrix[[COLOR=darkred]i][[COLOR=darkred]j]==88) {                 
                printf("Oops, the game ended in a tie!\n\n");                
                exit(0);             
             }         
        }    
    } 
}[/B]
```
Überleg dir mal, was hier denn genau passiert! Du gehst alle 9 Felder durch, und im Falle das: 
_Spieler1 ein Kreuz gemacht hat 
ODER
Spieler2 ein Kreuz gemacht hat_
bricht das Spiel ab. Das ist bei *jedem* Aufruf von checkTie() nach dem ersten Zug der Fall. Verständlich?

Du prüfst nach 2 Zügen das erste Mal die Funktion, also bricht nach 2 Zügen das Spiel auf jeden Fall ab.

Korrekt wäre: Du prüfst, ob auf allen Feldern bereits ein Stein/Kreuz liegt, und nur in diesem Falle brichst du das Spiel ab. Du könntest zB alle bisher gesetzten 
Kreuze zählen, und bei 9 brichst du das Spiel ab. Ich denke, dass das auch dein Ansatz war.

Hoffentlich konnte ich dir ein wenig helfen, es sind zwar noch ein paar mehr "Schwachstellen/Logikfehler" drinnen, allerdings betreffen sie dein jetztiges Problem nicht direkt.
Wenns nach den Verbesserungen immer noch nicht klappt, kann ich auch da ein paar Tipps geben.
Plane deinen Code immer Schritt für Schritt: Welche Schleifen brauche ich, was möchte ich genau abfragen, und noch wichtiger: Macht das, was ich geschrieben habe, auch wirklich genau das, was ich will? Programmieren ist sehr direkt, du sagst dem Computer genau, was er tun soll. Und genau das wird er dann auch tun! Wenn man auch nur kurze Zeit ein wenig unaufmerksam ist, und einfach das hinschreibt, was einem in den Kopf fällt (also so ist das bei mir) kann ich den Code quasi wegwerfen. Ein Logik-Fehler reicht aus, und das Programm tut nicht das was man eigentlich wollte, und man darf viel länger, als das "richtig" schreiben gedauert hätte, nach Fehlern suchen  .


----------



## boss3D (15. Oktober 2012)

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



Freddycbv schrieb:


> Wenn du das durchspielst, kommst du drauf, dass Spieler1 den letzten Zug macht, also das Unentschieden nach dem letzten Zug von PlayerOne und vor dem (5.) Zug von PlayerTwo festliegt. checkTie() muss also zwischen playerone() und playertwo()


Kann ich mir noch einigermaßen vorstellen.


Freddycbv schrieb:


> Du gehst alle 9 Felder durch, und im Falle das:
> _Spieler1 ein Kreuz gemacht hat
> ODER
> Spieler2 ein Kreuz gemacht hat_
> bricht das Spiel ab. Das ist bei *jedem* Aufruf von checkTie() nach dem ersten Zug der Fall. Verständlich?


Wie genau soll das hier mit den Spielern zusammenhängen? Ich dachte, der Code durchläuft nach jeder Runde die gesamte Matrix und prüft für jedes Feld, ob bereits ein X oder ein O darin gespeichert ist, und wenn ja --> unentschieden (da ja das Spiel im Falle eines Sieges schon vorher durch die jeweilige playerFunktion beendet worden wäre)


Freddycbv schrieb:


> Du prüfst nach 2 Zügen das erste Mal die Funktion, also bricht nach 2 Zügen das Spiel auf jeden Fall ab.


*[EDIT** ... Erklärung siehe Postingende*]
*Ok, jetzt funktioniert die Abfrage

```
void checkStatus() { [COLOR=seagreen]/* check status of the game after each round */   [COLOR=royalblue][B] int i=0;[/B]    int matrix[ROWS][COLUMNS] = { 0 };
    int newMatrix[ROWS][COLUMNS]= { 0 };

    newMatrix[ROWS][COLUMNS]=printMatrix(matrix, ROWS);

    while (checkWinner(newMatrix, ROWS)!=0) { [COLOR=seagreen]/* continue the game until one player has won ... */        playerOne(newMatrix, ROWS);
       [COLOR=royalblue][B] i++;
        if (i==5) { [/B][COLOR=seagreen]/* Player 1 has the last turn (9th). Afterwards, check for a tie */[B]
            checkTie(newMatrix, ROWS); [/B][COLOR=seagreen]/* ... or the game ends in a tie */[B]
        }[/B]        playerTwo(newMatrix, ROWS);
    }
}
```



Freddycbv schrieb:


> Korrekt wäre: Du prüfst, ob auf allen Feldern bereits ein Stein/Kreuz liegt, und nur in diesem Falle brichst du das Spiel ab. Du könntest zB alle bisher gesetzten
> Kreuze zählen, und bei 9 brichst du das Spiel ab. Ich denke, dass das auch dein Ansatz war.


Ja, das hatte ich vor.


Freddycbv schrieb:


> Hoffentlich konnte ich dir ein wenig helfen, es sind zwar noch ein paar mehr "Schwachstellen/Logikfehler" drinnen, allerdings betreffen sie dein jetztiges Problem nicht direkt.


Falls du mit "Schwachstellen/Logikfehler" ineffiziente Code-Teile meinst, okay, das weiß ich, dass es die gibt. Aber um sowas kümmere ich mich jetzt noch nicht wirklich. Ich bin immer noch Lerner in C und mein oberstes Ziel ist es ATM, immer schwierigere und längere Codes zu schreiben, die auch genauso funktionieren, wie sie sollen. Sobald ich mich in C wirklich sicher fühle, gehe ich solche Dinge wie Effizienz an ...  

Eine wirklich Schwachstelle ist wohl die while Schleife in der main, die, so wie ich das verstehe, endlos läuft und damit die Ausgabe der Spielzeit am Ende des Codes verhindert (das Programm gelangt dank der Schleife nie dort hin). Ansonsten wäre mir aber nichts aufgefallen, das jetzt kritisiert werden müsste. Die Profis unter euch wären vielleicht mit ein paar Funktionen weniger ausgekommen, aber das hängt dann auch wieder vom persönlichen Programmierstil ab. Ich zerlege ein großes Problem eben gerne in viele kleine und bearbeite diese möglichst unabhängig voneinander. So tue ich mir einfach leichter. Kann auch sein, dass das noch aus meiner Java-Zeit kommt. 

Was ich mir aber nicht unterstellen lasse, ist, dass ich einfach hinschreiben würde, was mir so durch den Kopf geht. Ich denke schon sehr intensiv nach beim Programmieren, nur manchmal verlaufe ich mich in eine vermeintliche Sackgasse (v.a. bei für mich neuen Dingen. Es sei erwähnt, dass ich noch nie zuvor mit Matrizen in C gearbeitet habe!). Entweder ich kann den gedanklichen Knoten dann lösen, oder ich versuche, einen Weg um das Problem herum zu finden. 

Werde mir die Funktion checkTie() jetzt noch einmal vornehmen. Würde mich wirklich freuen, wenn ich das noch hinbekäme ...

*[*EDIT]*
Hab's jetzt hinbekommen. Danke für den Hinweis, die Überprüfung zwischen die beiden Spieler-Funktionen zu packen!!!  

*[EDIT2]*
So, für ein Unentschieden wird jetzt schon die korrekte Spieldauer angezeigt. In der main musste ich dazu die Schleife komplett entfernen. Schritt für Schritt komme ich nun doch weiter. 


Spoiler





```
#include <stdio.h>
#include <time.h>

#define ROWS 3
#define COLUMNS 3

int checkWinner(int matrix[][COLUMNS], int rows) { [COLOR=seagreen]/* all possible ways to win the game */    if (matrix[0][0]==79 && matrix[0][1]==79 && matrix[0][2]==79) {
        return 0;
    } else if (matrix[1][0]==79 && matrix[1][1]==79 && matrix[1][2]==79) {
        return 0;
    } else if (matrix[2][0]==79 && matrix[2][1]==79 && matrix[2][2]==79) {
        return 0;
    } else if (matrix[0][0]==79 && matrix[1][0]==79 && matrix[2][0]==79) {
        return 0;
    } else if (matrix[0][1]==79 && matrix[1][1]==79 && matrix[2][1]==79) {
        return 0;
    } else if (matrix[0][2]==79 && matrix[1][2]==79 && matrix[2][2]==79) {
        return 0;
    } else if (matrix[0][0]==79 && matrix[1][1]==79 && matrix[2][2]==79) {
        return 0;
    } else if (matrix[0][2]==79 && matrix[1][1]==79 && matrix[2][0]==79) {
        return 0;
    } else if (matrix[0][0]==88 && matrix[0][1]==88 && matrix[0][2]==88) {
        return 0;
    } else if (matrix[1][0]==88 && matrix[1][1]==88 && matrix[1][2]==88) {
        return 0;
    } else if (matrix[2][0]==88 && matrix[2][1]==88 && matrix[2][2]==88) {
        return 0;
    } else if (matrix[0][0]==88 && matrix[1][0]==88 && matrix[2][0]==88) {
        return 0;
    } else if (matrix[0][1]==88 && matrix[1][1]==88 && matrix[2][1]==88) {
        return 0;
    } else if (matrix[0][2]==88 && matrix[1][2]==88 && matrix[2][2]==88) {
        return 0;
    } else if (matrix[0][0]==88 && matrix[1][1]==88 && matrix[2][2]==88) {
        return 0;
    } else if (matrix[0][2]==88 && matrix[1][1]==88 && matrix[2][0]==88) {
        return 0;
    } else {
        return 1;
    }
}

int checkTie(int matrix[][COLUMNS], int rows) { [COLOR=seagreen]/* check if the game ended in a tie */    int i=0, j=0;
    
    for (i=0; i<ROWS; i++) {
        for (j=0; j<COLUMNS; j++) {
            if (matrix[i][j]==79 || matrix[i][j]==88) {
                printf("Oops, the game ended in a tie!\n");
                return 0;
            }
        }
    }

    return 1;
}

int checkStatus() { [COLOR=seagreen]/* check status of the game after each round */    int i=0;
    int matrix[ROWS][COLUMNS] = { 0 };
    int newMatrix[ROWS][COLUMNS]= { 0 };

    newMatrix[ROWS][COLUMNS]=printMatrix(matrix, ROWS);

    while (checkWinner(newMatrix, ROWS)!=0) { [COLOR=seagreen]/* continue the game until one player has won ... */        playerOne(newMatrix, ROWS);
        i++;
        if (i==5 && (checkTie(newMatrix, ROWS)==0)) { [COLOR=seagreen]/* Player 1 has the last turn (9th). Afterwards, check for a tie */             return 0;  [COLOR=seagreen]/* ... or the game ends in a tie */             }
        }
        playerTwo(newMatrix, ROWS);
    }

    return 1;
}

int playerOne(int matrix[][COLUMNS], int rows) {
    int x1=0, y1=0, error=0;

    printf("Player 1, it's your turn. Please enter coordinates: ");
    scanf("%d %d", &x1, &y1);
    putchar('\n');
    if ((x1 <= 0 || x1 > 3) || (y1 <= 0 || y1 > 3)) { [COLOR=seagreen]/* if Player 1's input is invalid, ask again */        printf("\nINVALID INPUT! Try again ...\n\n");
        playerOne(matrix, ROWS);
        error=1;
    } else if (matrix[x1-1][y1-1]==79 || matrix[x1-1][y1-1]==88) { [COLOR=seagreen]/* if Player 1 chooses a field that is already taken, ask again */        printf("Field already taken! Try again ...\n\n");
        playerOne(matrix, ROWS);
        error=2;
    }

    if (error != 1 && error != 2) { [COLOR=seagreen]/* only print matrix if user input is valid */        matrix[x1-1][y1-1]=88; [COLOR=seagreen]/* ASCII value for 'X' */        printMatrix(matrix, ROWS);
        if (checkWinner(matrix, ROWS)==0) {
            printf("Congratulations, Player 1! You won the game.\n\n");
        } 
    }
    return matrix[ROWS][COLUMNS];
}

int playerTwo(int matrix[][COLUMNS], int rows) {
    int x2=0, y2=0, error=0;

    printf("Player 2, it's your turn. Please enter coordinates: ");
    scanf("%d %d", &x2, &y2);
    putchar('\n');
    if ((x2 <= 0 || x2 > 3) || (y2 <= 0 || y2 > 3)) { [COLOR=seagreen]/* if Player 2's input is invalid, ask again */        printf("\nINVALID INPUT! Try again ...\n\n");
        playerTwo(matrix, ROWS);
        error=1;
    } else if (matrix[x2-1][y2-1]==79 || matrix[x2-1][y2-1]==88) { [COLOR=seagreen]/* if Player 2 chooses a field that is already taken, ask again */        printf("Field already taken! Try again ...\n\n");
        playerTwo(matrix, ROWS);
        error=2;
    }

    if (error != 1 && error != 2) { [COLOR=seagreen]/* only print matrix if user input is valid */        matrix[x2-1][y2-1]=79; [COLOR=seagreen]/* ASCII value for 'O' */        printMatrix(matrix, ROWS);
        if (checkWinner(matrix, ROWS)==0) {
            printf("Congratulations, Player 2! You won the game.\n\n");
        } 
    }
    return matrix[ROWS][COLUMNS];
}

int printMatrix(int matrix[][COLUMNS], int rows) {
    int i=0, j=0;
    int resultMatrix[ROWS][COLUMNS] = { 0 };

    for (i=0; i<ROWS; i++) {
        for (j=0; j<COLUMNS; j++) {
            if (matrix[i][j] == 88 || matrix[i][j] == 79) {
                (j<2) ? (printf(" %c |", matrix[i][j])) : (printf(" %c", matrix[i][j]));
            } else {
                (j<2) ? (printf("   |", matrix[i][j])) : (printf("", matrix[i][j]));
            }
            resultMatrix[i][j]=matrix[i][j];
        }
        printf(i<2 ? "\n---+---+---\n" : "");
     }
     printf("\n\n");

     return resultMatrix[i][j];
}

int main(void) {
    int i=0;
    double time1=0.0, time2=0.0;

    time1=clock();

    printf("TIC TAC TOE\n\n");
    printf("Player 1 ... X\nPlayer 2 ... O\n\n");

   [COLOR=royalblue][B] if (checkStatus()==0) {
        time2=clock()-time1;
        time2=time2/CLOCKS_PER_SEC;
        printf("\nThe game lasted %.2lf minutes.\n\n", time2/60);
    }[/B]
    return 0;
}
```



Jetzt nur noch eine Zeitmessung für den Siegesfall eines Spielers hinkriegen, dann hätte ich es geschafft ...

*[EDIT3]*

*MADE IT!!!* 

Blau markiert sind jene Änderungen, die notwendig waren, um das gewünschte Ergebnis zu liefern:


Spoiler





```
#include <stdio.h>
#include <time.h>

#define ROWS 3
#define COLUMNS 3

int checkWinner(int matrix[][COLUMNS], int rows) { [COLOR=seagreen]/* all possible ways to win the game */    if (matrix[0][0]==79 && matrix[0][1]==79 && matrix[0][2]==79) {
        return 0;
    } else if (matrix[1][0]==79 && matrix[1][1]==79 && matrix[1][2]==79) {
        return 0;
    } else if (matrix[2][0]==79 && matrix[2][1]==79 && matrix[2][2]==79) {
        return 0;
    } else if (matrix[0][0]==79 && matrix[1][0]==79 && matrix[2][0]==79) {
        return 0;
    } else if (matrix[0][1]==79 && matrix[1][1]==79 && matrix[2][1]==79) {
        return 0;
    } else if (matrix[0][2]==79 && matrix[1][2]==79 && matrix[2][2]==79) {
        return 0;
    } else if (matrix[0][0]==79 && matrix[1][1]==79 && matrix[2][2]==79) {
        return 0;
    } else if (matrix[0][2]==79 && matrix[1][1]==79 && matrix[2][0]==79) {
        return 0;
    } else if (matrix[0][0]==88 && matrix[0][1]==88 && matrix[0][2]==88) {
        return 0;
    } else if (matrix[1][0]==88 && matrix[1][1]==88 && matrix[1][2]==88) {
        return 0;
    } else if (matrix[2][0]==88 && matrix[2][1]==88 && matrix[2][2]==88) {
        return 0;
    } else if (matrix[0][0]==88 && matrix[1][0]==88 && matrix[2][0]==88) {
        return 0;
    } else if (matrix[0][1]==88 && matrix[1][1]==88 && matrix[2][1]==88) {
        return 0;
    } else if (matrix[0][2]==88 && matrix[1][2]==88 && matrix[2][2]==88) {
        return 0;
    } else if (matrix[0][0]==88 && matrix[1][1]==88 && matrix[2][2]==88) {
        return 0;
    } else if (matrix[0][2]==88 && matrix[1][1]==88 && matrix[2][0]==88) {
        return 0;
    } else {
        return 1;
    }
}

int checkTie(int matrix[][COLUMNS], int rows) { [COLOR=seagreen]/* check if the game ended in a tie */    int i=0, j=0;
    
    for (i=0; i<ROWS; i++) {
        for (j=0; j<COLUMNS; j++) {
            if (matrix[i][j]==79 || matrix[i][j]==88) {
                printf("Oops, the game ended in a tie!\n");
                return 0;
            }
        }
    }

    return 1;
}

int checkStatus() { [COLOR=seagreen]/* check status of the game after each round */    int i=0;
    int matrix[ROWS][COLUMNS] = { 0 };
    int newMatrix[ROWS][COLUMNS]= { 0 };

    newMatrix[ROWS][COLUMNS]=printMatrix(matrix, ROWS);

    while (checkWinner(newMatrix, ROWS)!=0) { [COLOR=seagreen]/* continue the game until one player has won ... */[COLOR=royalblue][B]        if (playerOne(newMatrix, ROWS)==0) {
            return 0;
        }[/B]        i++;
        if (i==5 && (checkTie(newMatrix, ROWS)==0)) {[COLOR=seagreen] /* Player 1 has the last turn (9th). Afterwards, check for a tie */            return 0; [COLOR=seagreen] /* ... or the game ends in a tie */        }
    [COLOR=royalblue][B]    if (playerTwo(newMatrix, ROWS)==0) {
            return 0;
        }[/B]    }

    return 1;
}

int playerOne(int matrix[][COLUMNS], int rows) {
    int x1=0, y1=0, error=0;

    printf("Player 1, it's your turn. Please enter coordinates: ");
    scanf("%d %d", &x1, &y1);
    putchar('\n');
    if ((x1 <= 0 || x1 > 3) || (y1 <= 0 || y1 > 3)) { [COLOR=seagreen]/* if Player 1's input is invalid, ask again */        printf("\nINVALID INPUT! Try again ...\n\n");
        playerOne(matrix, ROWS);
        error=1;
    } else if (matrix[x1-1][y1-1]==79 || matrix[x1-1][y1-1]==88) { [COLOR=seagreen]/* if Player 1 chooses a field that is already taken, ask again */        printf("Field already taken! Try again ...\n\n");
        playerOne(matrix, ROWS);
        error=2;
    }

    if (error != 1 && error != 2) { [COLOR=seagreen]/* only print matrix if user input is valid */        matrix[x1-1][y1-1]=88;[COLOR=seagreen] /* ASCII value for 'X' */        printMatrix(matrix, ROWS);
        if (checkWinner(matrix, ROWS)==0) {
            printf("Congratulations, Player 1! You won the game.\n");
            [COLOR=royalblue][B]return 0;[/B]        } 
    }
    return matrix[ROWS][COLUMNS];
}

int playerTwo(int matrix[][COLUMNS], int rows) {
    int x2=0, y2=0, error=0;

    printf("Player 2, it's your turn. Please enter coordinates: ");
    scanf("%d %d", &x2, &y2);
    putchar('\n');
    if ((x2 <= 0 || x2 > 3) || (y2 <= 0 || y2 > 3)) { [COLOR=seagreen]/* if Player 2's input is invalid, ask again */        printf("\nINVALID INPUT! Try again ...\n\n");
        playerTwo(matrix, ROWS);
        error=1;
    } else if (matrix[x2-1][y2-1]==79 || matrix[x2-1][y2-1]==88) { [COLOR=seagreen]/* if Player 2 chooses a field that is already taken, ask again */        printf("Field already taken! Try again ...\n\n");
        playerTwo(matrix, ROWS);
        error=2;
    }

    if (error != 1 && error != 2) { [COLOR=seagreen]/* only print matrix if user input is valid */        matrix[x2-1][y2-1]=79; [COLOR=seagreen]/* ASCII value for 'O' */        printMatrix(matrix, ROWS);
        if (checkWinner(matrix, ROWS)==0) {
            printf("Congratulations, Player 2! You won the game.\n");
            [COLOR=royalblue][B]return 0;[/B]        } 
    }
    return matrix[ROWS][COLUMNS];
}

int printMatrix(int matrix[][COLUMNS], int rows) {
    int i=0, j=0;
    int resultMatrix[ROWS][COLUMNS] = { 0 };

    for (i=0; i<ROWS; i++) {
        for (j=0; j<COLUMNS; j++) {
            if (matrix[i][j] == 88 || matrix[i][j] == 79) {
                (j<2) ? (printf(" %c |", matrix[i][j])) : (printf(" %c", matrix[i][j]));
            } else {
                (j<2) ? (printf("   |", matrix[i][j])) : (printf("", matrix[i][j]));
            }
            resultMatrix[i][j]=matrix[i][j];
        }
        printf(i<2 ? "\n---+---+---\n" : "");
     }
     printf("\n\n");

     return resultMatrix[i][j];
}

int main(void) {
    int i=0;
    double time1=0.0, time2=0.0;

    time1=clock();

    printf("TIC TAC TOE\n\n");
    printf("Player 1 ... X\nPlayer 2 ... O\n\n");

    [COLOR=royalblue][B]if (checkStatus()==0) {
        time2=clock()-time1;
        time2=time2/CLOCKS_PER_SEC;
        printf("\nThe game lasted %.2lf minutes.\n\n", time2/60);
    }[/B]
    return 0;
}
```



Vielen Dank noch einmal, dass du mich aus der gedanklichen Sackgasse geführt hast, Freddycbv! Jetzt können wir über so Dinge, wie Effizienz und "Schwachstellen" im Code reden. Jetzt, wo alles so läuft, wie ich das wollte, habe ich nichts gegen Optimierungen.


----------



## Freddycbv (16. Oktober 2012)

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

Super, dass es jetzt funktioniert!

Mit den Logikfehlern meine ich, dass deine Funktionen nicht immer das machen, für das ihr Name eigentlich steht. Das verwirrt ein wenig, und ist nicht ganz so "sauber"

1. checkWinner() prüft nicht, WER gewonnen hat, sondern ob das Spiel zuende ist (weil irgendeiner gewonnen hat). Besser wäre, wenn es direkt prüfen würde, wer gewonnen hat, und entsprechend etwas zurückgibt. Bei deiner jetzigen Implementierung geht es eigentlich auch so wie es bisher ist (Das Spiel funktioniert ja  ), weil du checkWinner() immer nach dem Zug eines Spielers aufrufst, und beim ersten, wo CheckWinner() "0" zurückgibt, der hat gewonnen. 

2. checkStatus() gibt immer 0 zurück. 
Ein Spiel kann ja nur in 3 Situationen enden: 
1) Niemand gewonnen: 
	
	



```
if (i==5 && (checkTie(newMatrix, ROWS)==0)) 
{[COLOR=seagreen] /* Player 1 has the last turn (9th). Afterwards, check for a tie */    return 0; [COLOR=seagreen] /* ... or the game ends in a tie */}
```
2) Spieler 1 gewonnen: 
	
	



```
if (playerOne(newMatrix, ROWS)==0) 
{      
     return 0;         
}
```
3) Spieler 2 gewonnen: 
	
	



```
[COLOR=royalblue][COLOR=black]if (playerTwo(newMatrix, ROWS)==0) 
{       
    return 0;        
}
```
In allen 3 Fällen wird 0 zurückgegeben. 
Wäre es nicht besser, wenn checkStatus() das Ergebniss des Spieles zurüchgibt? ZB. 0 für unentschieden, 1 für Sieg von Spieler1 und 2 für Spieler2?
Wenn du das machst, musst du nur in der main() aufpassen, weil die Zeit (bisher) nur ausgegeben wird, wenn checkStatus() 0 zurückgibt:

```
if (checkStatus()==0) 
{     
    time2=clock()-time1;    
    time2=time2/CLOCKS_PER_SEC;    
    printf("\nThe game lasted %.2lf minutes.\n\n", time2/60);  
}
```
Du kannst hier getrost das if(){} rausnehmen, und die Anweisungen in jedem Fall ausführen:

```
checkStatus()        
time2=clock()-time1;         
time2=time2/CLOCKS_PER_SEC;         
printf("\nThe game lasted %.2lf minutes.\n\n", time2/60);
```
Wenn CheckStatus() dann auch 0, 1 oder 2 zurückgibt (je nach Ausgang des Spieles) kannst du hier dann auch nach dem Gewinner prüfen:

```
int GameResult = [COLOR=royalblue][COLOR=black]checkStatus();
if(GameResult == 0 ){...}
else if(GameResult == 1){...}
else if(GameResult == 2){...}
```
3. checkTie()


boss3D schrieb:


> Wie genau soll das hier mit den Spielern zusammenhängen? Ich dachte, der Code durchläuft nach jeder Runde die gesamte Matrix und prüft für jedes Feld, ob bereits ein X oder ein O darin gespeichert ist, und wenn ja --> unentschieden (da ja das Spiel im Falle eines Sieges schon vorher durch die jeweilige playerFunktion beendet worden wäre)


Richtig! Es prüft für *jedes* Feld, ob bereits ein X oder ein O darin gespeichert ist. Es reicht 1 besetztes Feld, und es gibt "Unentschieden" zurück.
Es prüft nicht, ob in *allen *Feldern bereits ein X oder O gespeichert ist! Verstehst du den Unterschied? Du könntest zB. alle belegten Felder zählen (und nicht schon beim ersten Feld "Unentschieden" zurückgeben), und bei 9 belegten Feldern ein "Unentschieden" zurückgeben.


Hoffentlich bin ich nicht zu kleinlich  Ich mag strukturierten Aufbau, das hilft vorallem, wenn man seine Projekte später nochmal erweitern will.


----------



## boss3D (16. Oktober 2012)

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

Bei deinen Punkten #1 und #2 kann man wohl darüber streiten, was jetzt der "sauberere" Weg ist. Mir persönlich gefällt ehrlich gesagt meine Variante besser. Außerdem macht es ja für den Computer keinen Unterschied, welcher der beiden Spieler gewinnt und die beiden Spieler (die Menschen) werden sich den Code hinter dem Programm wohl nie anschauen. Und nachträgliche Erweiterungen kann man in dem Fall wohl auch ausschließen, weil nie mehr als maximal 2 Personen TIC-TAC-TOE spielen können und für 2 Personen ist der Code ja schon geschrieben.  

Wieso ich angeblich das if aus der main rausnehmen kann, kann ich gerade nicht ganz nachvollziehen. Ebenso, wieso _checkStatus()_ immer 0 zurückgeben soll ...

^^ _checkStatus()_ führt seine Überprüfungen so lange durch, bis entweder _checkWinner()_ 0 zurückgibt, oder _checkTie()_ 0 zurückgibt. Das ist ja nicht nach jeder Runde der Fall?!


Freddycbv schrieb:


> Richtig! Es prüft für *jedes* Feld, ob  bereits ein X oder ein O darin gespeichert ist. Es reicht 1 besetztes  Feld, und es gibt "Unentschieden" zurück.


Für mein Verständnis widersprechen sich deine beiden Sätze hier. Es soll ja auch für jedes Feld überprüft werden, ob ein X oder ein O darin gespeichert ist und wenn das in allen 9 Feldern der Fall ist --> unentschieden.


Freddycbv schrieb:


> Es  prüft nicht, ob in *allen *Feldern bereits ein X oder O  gespeichert ist!


Warum nicht? Ich glaube schon, dass es das tut.  Muss es eigentlich sogar, weil sonst _checkTie()_ nicht richtig funktionieren würde und das tut es aber.

Die Funktion _checkTie()_ wird ja erst verlassen, wenn beide for-Schleifen komplett abgearbeitet sind und was die machen, ist, die gesamte Matrix horizontal und vertikal zu durchlaufen. Damitz sollte also JEDES Feld erwischt werden.


----------



## Freddycbv (16. Oktober 2012)

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

Dann beschränken wir uns auf Punkt 3:
Ich behaupte, CheckTie arbeitet inkorrekt! Das Programm läuft nur korrekt wegen folgendem Punkt (in checkStatus):

```
if (i==5 && (checkTie(newMatrix, ROWS)==0)) 
{[COLOR=seagreen] /* Player 1 has the last turn (9th). Afterwards, check for a tie */       
     return 0; [COLOR=seagreen] /* ... or the game ends in a tie */         
}
```
Ich behaupte: checkTie() gibt IMMER 0 zurück, nachdem der erste Stein gesetzt wurde.
d.h. "&& (checkTie(newMatrix, ROWS)==0)" in der If-Abfage kann man weglassen.
Wenn i==5, ist automatisch das Spielbrett voll, dh. es ist unentschieden.
Probiers aus! Du brauchst an dieser Stelle checkTie() nicht, es ist überflüssig, und arbeitet zudem inkorrekt.
Warum inkorrekt?

```
int checkTie(int matrix[][COLUMNS], int rows) 
{ [COLOR=seagreen]/* check if the game ended in a tie */      int i=0, j=0;    
      for (i=0; i<ROWS; i++) 
      { 
          for (j=0; j<COLUMNS; j++) 
         {             
              if (matrix[i][j]==79 || matrix[i][j]==88) 
             {
                 printf("Oops, the game ended in a tie!\n");
                 return 0;
             }
         }
     }      
    return 1; 
}
```
Das ist deine Funktion. Das ist der kritische Teil: 
	
	



```
if (matrix[i][j]==79 || matrix[i][j]==88) {
    printf("Oops, the game ended in a tie!\n");
    return 0;
}
```
i bewegt sich zwischen 0 und 2, genauso j.
In der If steht: Wenn auf dem Feld_[j] ein O oder ein X ist, dann gebe 0 zurück.
Alle 9 Felder werden durchgegangen, und wenn auch nur auf EINEM ein O oder X ist, wird 0 zurückgegeben:


Spoiler



if(Feld[0][0] == 79 || Feld[0][0] == 88) return 0;
if(Feld[0][1] == 79 || Feld[0][1] == 88) return 0; 
if(Feld[0][2] == 79 || Feld[0][2] == 88) return 0;
if(Feld[1][0] == 79 || Feld[1][0] == 88) return 0; 
if(Feld[1][1] == 79 || Feld[1][1] == 88) return 0; 
if(Feld[1][2] == 79 || Feld[1][2] == 88) return 0; 
if(Feld[2][0] == 79 || Feld[2][0] == 88) return 0; 
if(Feld[2][1] == 79 || Feld[2][1] == 88) return 0; 
if(Feld[2][2] == 79 || Feld[2][2] == 88) return 0;



_


----------



## boss3D (16. Oktober 2012)

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



Freddycbv schrieb:


> Ich behaupte: checkTie() gibt IMMER 0 zurück, nachdem der erste Stein gesetzt wurde.
> d.h. "&& (checkTie(newMatrix, ROWS)==0)" in der If-Abfage kann man weglassen.
> Wenn i==5, ist automatisch das Spielbrett voll, dh. es ist unentschieden.
> Probiers aus!


Hab's ausprobiert und festgestellt, dass dann _"Oops, the game ended in a tie!"_ bei einem Unentschieden nicht mehr ausgegeben wird. Offensichtlich kann man den zweiten Teil der if-Abfrage nicht löschen. Hast du es ausprobiert?


Freddycbv schrieb:


> Du brauchst an dieser Stelle checkTie() nicht, es ist überflüssig, und arbeitet zudem inkorrekt.
> Warum inkorrekt?
> Das ist der kritische Teil:
> 
> ...


_
Ich habe schon in deinem vorigen Posting verstanden, wie du dir das Verhalten der beiden for-Schleifen vorstellst. Und ich habe auch schon darauf geantwortet ...


Freddycbv schrieb:



			Es  prüft nicht, ob in *allen *Feldern bereits ein X oder O  gespeichert ist!
		
Zum Vergrößern anklicken....




boss3D schrieb:



			Warum nicht? Ich glaube schon, dass es das tut.   Muss es eigentlich sogar, weil sonst checkTie() nicht richtig  funktionieren würde und das tut es aber.

Die Funktion  checkTie() wird ja erst verlassen, wenn beide for-Schleifen  komplett abgearbeitet sind und was die machen, ist, die gesamte Matrix  horizontal und vertikal zu durchlaufen. Damit sollte also JEDES Feld  erwischt werden.
		
Zum Vergrößern anklicken....

Wenn du recht hast, was schon sein kann, dann verstehe ich aber nicht, wieso der Code in der aktuellen Version wunderbar funktioniert. Auch wenn es tatsächlich nicht so sein sollte, macht es im Spiel den Anschein, als würde die gesamte (!) Matrix auf 79er und 88er durchsucht werden (ob sie voll damit ist).

*[EDIT]*
Jetzt habe ich verstanden, was du mir sagen willst!  

Die ganze Funktion checkTie() ist umsonst, weil das i==5 eh nur passieren kann, wenn es nicht schon zuvor zu einem Sieg eines Spielers gekommen ist. Und wenn es passiert, haben wir automatisch ein Unentschieden. Mein Code hat die Funktion checkTie() nur gebraucht, weil dort eben die Ausgabe von "Oops, the game ended in a tie!" passiert.

Wenn ich also besagte Ausgabe an der richtigen Stelle in checkStatus() reinpacke, kann ich checkTie() komplett löschen:


Spoiler






		Code:
	

#include <stdio.h>
#include <time.h>

#define ROWS 3
#define COLUMNS 3

int checkWinner(int matrix[][COLUMNS], int rows) { /* all possible ways to win the game */
    if (matrix[0][0]==79 && matrix[0][1]==79 && matrix[0][2]==79) {
        return 0;
    } else if (matrix[1][0]==79 && matrix[1][1]==79 && matrix[1][2]==79) {
        return 0;
    } else if (matrix[2][0]==79 && matrix[2][1]==79 && matrix[2][2]==79) {
        return 0;
    } else if (matrix[0][0]==79 && matrix[1][0]==79 && matrix[2][0]==79) {
        return 0;
    } else if (matrix[0][1]==79 && matrix[1][1]==79 && matrix[2][1]==79) {
        return 0;
    } else if (matrix[0][2]==79 && matrix[1][2]==79 && matrix[2][2]==79) {
        return 0;
    } else if (matrix[0][0]==79 && matrix[1][1]==79 && matrix[2][2]==79) {
        return 0;
    } else if (matrix[0][2]==79 && matrix[1][1]==79 && matrix[2][0]==79) {
        return 0;
    } else if (matrix[0][0]==88 && matrix[0][1]==88 && matrix[0][2]==88) {
        return 0;
    } else if (matrix[1][0]==88 && matrix[1][1]==88 && matrix[1][2]==88) {
        return 0;
    } else if (matrix[2][0]==88 && matrix[2][1]==88 && matrix[2][2]==88) {
        return 0;
    } else if (matrix[0][0]==88 && matrix[1][0]==88 && matrix[2][0]==88) {
        return 0;
    } else if (matrix[0][1]==88 && matrix[1][1]==88 && matrix[2][1]==88) {
        return 0;
    } else if (matrix[0][2]==88 && matrix[1][2]==88 && matrix[2][2]==88) {
        return 0;
    } else if (matrix[0][0]==88 && matrix[1][1]==88 && matrix[2][2]==88) {
        return 0;
    } else if (matrix[0][2]==88 && matrix[1][1]==88 && matrix[2][0]==88) {
        return 0;
    } else {
        return 1;
    }
}

int checkStatus() { /* check status of the game after each round */
    int i=0;
    int matrix[ROWS][COLUMNS] = { 0 };
    int newMatrix[ROWS][COLUMNS]= { 0 };

    newMatrix[ROWS][COLUMNS]=printMatrix(matrix, ROWS);

    while (checkWinner(newMatrix, ROWS)!=0) { /* continue the game until one player has won ... */
        if (playerOne(newMatrix, ROWS)==0) {
            return 0;
        }
       [COLOR=royalblue][B] i++;
        if (i==5) { [/B][COLOR=seagreen]/* If neither player has won until the last round (= playerOne's fifth turn), it has to be a tie */[B]
            printf("Oops, the game ended in a tie!\n");
            return 0;  [/B][B]
        }[/B]        if (playerTwo(newMatrix, ROWS)==0) {
            return 0;
        }
    }

    return 1;
}

int playerOne(int matrix[][COLUMNS], int rows) {
    int x1=0, y1=0, error=0;

    printf("Player 1, it's your turn. Please enter coordinates: ");
    scanf("%d %d", &x1, &y1);
    putchar('\n');
    if ((x1 <= 0 || x1 > 3) || (y1 <= 0 || y1 > 3)) { /* if Player 1's input is invalid, ask again */
        printf("INVALID INPUT! Try again ...\n\n");
        playerOne(matrix, ROWS);
        error=1;
    } else if (matrix[x1-1][y1-1]==79 || matrix[x1-1][y1-1]==88) { /* if Player 1 chooses a field that is already taken, ask again */
        printf("Field already taken! Try again ...\n\n");
        playerOne(matrix, ROWS);
        error=2;
    }

    if (error != 1 && error != 2) { /* only print matrix if user input is valid */
        matrix[x1-1][y1-1]=88; /* ASCII value for 'X' */
        printMatrix(matrix, ROWS);
        if (checkWinner(matrix, ROWS)==0) {
            printf("Congratulations, Player 1! You won the game.\n");
            return 0;
        } 
    }
    return matrix[ROWS][COLUMNS];
}

int playerTwo(int matrix[][COLUMNS], int rows) {
    int x2=0, y2=0, error=0;

    printf("Player 2, it's your turn. Please enter coordinates: ");
    scanf("%d %d", &x2, &y2);
    putchar('\n');
    if ((x2 <= 0 || x2 > 3) || (y2 <= 0 || y2 > 3)) { /* if Player 2's input is invalid, ask again */
        printf("INVALID INPUT! Try again ...\n\n");
        playerTwo(matrix, ROWS);
        error=1;
    } else if (matrix[x2-1][y2-1]==79 || matrix[x2-1][y2-1]==88) { /* if Player 2 chooses a field that is already taken, ask again */
        printf("Field already taken! Try again ...\n\n");
        playerTwo(matrix, ROWS);
        error=2;
    }

    if (error != 1 && error != 2) { /* only print matrix if user input is valid */
        matrix[x2-1][y2-1]=79; /* ASCII value for 'O' */
        printMatrix(matrix, ROWS);
        if (checkWinner(matrix, ROWS)==0) {
            printf("Congratulations, Player 2! You won the game.\n");
            return 0;
        } 
    }
    return matrix[ROWS][COLUMNS];
}

int printMatrix(int matrix[][COLUMNS], int rows) {
    int i=0, j=0;
    int resultMatrix[ROWS][COLUMNS] = { 0 };

    for (i=0; i<ROWS; i++) {
        for (j=0; j<COLUMNS; j++) {
            if (matrix[i][j] == 88 || matrix[i][j] == 79) {
                (j<2) ? (printf(" %c |", matrix[i][j])) : (printf(" %c", matrix[i][j]));
            } else {
                (j<2) ? (printf("   |", matrix[i][j])) : (printf("", matrix[i][j]));
            }
            resultMatrix[i][j]=matrix[i][j];
        }
        printf(i<2 ? "\n---+---+---\n" : "");
     }
     printf("\n\n");

     return resultMatrix[i][j];
}

int main(void) {
    int i=0;
    double time1=0.0, time2=0.0;

    time1=clock();

    printf("TIC TAC TOE\n\n");
    printf("Player 1 ... X\nPlayer 2 ... O\n\n");

    if (checkStatus()==0) {
        time2=clock()-time1;
        time2=time2/CLOCKS_PER_SEC;
        printf("\nThe game lasted %.2lf minutes.\n\n", time2/60);
    }

    return 0;
}




Vielen Dank für die Mühe, mir das beizubringen. Aber wie du siehst, sie war nicht umsosnt. _


----------



## Freddycbv (16. Oktober 2012)

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

(EDIT)
war nicht ganz einfach, aber bitteschön


----------



## nay (17. Oktober 2012)

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

Dein Problem hat mich auf eine Idee gebracht.

Als ich mir deinen Code angeschaut habe fiel mir gleich die *if else if* Kette auf, die überprüft ob ein Spieler gewonnen hat. Mir hat das nicht so gut gefallen also habe ich mir gedacht wie ein Algorithmus aussehen würde, der

- unabhängig von der Spielfeldgröße
- unabhängig von der Länge einer Gewinnkette

überprüft ob ein Spieler gewonnen hat.

Ich habe mir dazu ein paar Gedanken gemacht und werde dazu in den nächsten Tagen etwas posten. Vielleicht hast du ja auch Lust dich damit auseinanderzusetzen und wir können ein wenig diskutieren und vergleichen


----------



## boss3D (17. Oktober 2012)

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

Ja, poste ruhig! Ich schaue mir deine Vorschläge gerne an.


----------



## Freddycbv (19. Oktober 2012)

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

ich finde die überlegung von nay auch sehr interessant.
Habe mir jetzt auch eine Version der Funktion gebastelt, allerdings ist diese auf quadratische Spielfelder beschränkt.
Länge der Gewinnkette als auch Anzahl der Spieler ist dabei egal.
Ich warte allerdings mit dem Posten, da ich mir erstmal ein Testprogramm schreiben muss, um zu prüfen, ob meine Funktion auch richtig läuft


----------



## boss3D (8. November 2012)

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

*Neues Beispiel ...* 

Man schreibe ein Programm, dass eine Matrix horizontal und vertikal nach eingegebenen Wörtern durchsucht. Es soll möglich sein, die gesamte Matrix auszugeben, die Überprüfung durchzuführen und das Programm zu beenden. Bei enthaltenen Wörtern sollen die Koordinaten des Anfangsbuchstaben ausgegeben werden.
(Die Matrix ist gegeben bzw. darf fix definiert werden.)

Den Code hätte ich auch schon komplett fertig, so wie ich mir das vorstelle, nur leider sagt er mir immer, dass das gesuchte Wort nicht in der Matrix enthalten wäre, egal was ich eingebe (also auch bei Wörtern, die enthalten sind!). Daraus schließe ich, dass die ersten beiden if Abfragen in meiner searchMatrix() Funktion, warum auch immer, übersprungen werden und er automatisch im else landet. Die Frage: Warum?


Spoiler





```
#include <stdio.h>
#include <stdlib.h>

#define ROWS 12
#define COLUMNS 12

void searchMatrix(char *string, int matrix[][COLUMNS], int rows) {
    int i=0, j=0, k=0, length=0;

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

[B][COLOR=royalblue]    while (i != ROWS && j != COLUMNS) { [/B][COLOR=seagreen]/* Until the whole matrix is searched ... */[B][COLOR=royalblue]
        if (*(string+i)==matrix[i][j]) {[/B][COLOR=seagreen] /* ... search each row ... */[B][COLOR=royalblue]
            for (k=0; k<length; k++) {
                printf("%c", *(string+k));
            }
            printf(" found horizontally! %d %d\n", i+1, j+1);
        } else if (*(string+j)==matrix[i][j]) { [/B][COLOR=seagreen]/* ... and each column for a match. */[B][COLOR=royalblue]
            for (k=0; k<length; k++) {
                printf("%c", *(string+k));
            }
            printf(" found vertically! %d %d\n", i+1, j+1);
        } else { [/B][COLOR=seagreen]/* If no match is found, say so. */[B][COLOR=royalblue]
            for (k=0; k<length; k++) {
                printf("%c", *(string+k));
            }
            printf(" not found!\n");
            break;
        }
        i++;
        j++;
    }[/B]    
}

void printMatrix(int matrix[][COLUMNS], int rows) {
    int i=0, j=0;

    printf("\n+---+---+---+---+---+---+---+---+---+---+---+---+\n");
    for (i=0; i<ROWS; i++) {
        for (j=0; j<COLUMNS; j++) {
            printf("| %c ", matrix[i][j]);
            if (j==11) {
                printf("|\n+---+---+---+---+---+---+---+---+---+---+---+---+\n");
            }
        }
    }
}

int main(void) {
    int matrix[ROWS][COLUMNS] = {{'X', 'S', 'E', 'C', 'U', 'R', 'I', 'T', 'Y', 'C', 'O', 'T'},
                                 {'M', 'E', 'D', 'I', 'A', 'H', 'E', 'R', 'C', 'S', 'T', 'A'},
                                 {'K', 'C', 'F', 'X', 'J', 'A', 'E', 'S', 'I', 'I', 'L', 'S'},
                                 {'M', 'U', 'I', 'N', 'T', 'R', 'U', 'S', 'I', 'O', 'N', 'K'},
                                 {'A', 'R', 'R', 'Z', 'F', 'W', 'N', 'K', 'I', 'G', 'V', 'Z'},
                                 {'L', 'E', 'E', 'N', 'C', 'R', 'Y', 'P', 'T', 'I', 'O', 'N'},
                                 {'W', 'K', 'W', 'O', 'R', 'M', 'P', 'E', 'U', 'O', 'J', 'X'},
                                 {'A', 'V', 'A', 'M', 'D', 'N', 'D', 'P', 'J', 'H', 'A', 'L'},
                                 {'R', 'L', 'L', 'N', 'V', 'I', 'R', 'U', 'S', 'P', 'E', 'E'},
                                 {'E', 'W', 'L', 'D', 'D', 'E', 'X', 'O', 'L', 'T', 'P', 'U'},
                                 {'X', 'J', 'P', 'R', 'C', 'T', 'C', 'P', 'A', 'P', 'R', 'C'},
                                 {'G', 'K', 'B', 'U', 'F', 'F', 'E', 'R', 'S', 'L', 'T', 'B'}};
    int i=0;
    char string[13];

    printf("Matrix Search - Available commands:\n");
    printf("1 .. Enter a search string\n");
    printf("9 .. Print the matrix\n");
    printf("0 .. Quit the program\n");
    
    for ( ; ; ) { [COLOR=seagreen]/* The program should only end if the user enters 0. */        printf("\nPlease enter your command: ");
        scanf("%d", &i);
        if (i==0) {
            exit(0);
        } else if (i==9) {
            printMatrix(matrix, ROWS);
        } else if (i==1) {
            printf("Please enter search string: ");
            scanf("%s", &string);
            searchMatrix(string, matrix, ROWS);
        }
    }

    return 0;
}
```


----------



## DarkMo (8. November 2012)

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

zu der blau markierten while schleife... das kann doch so nix werden ^^ gehs doch mal im kopf stück für stück durch:
du fängst bei 0|0 an und schaust das gelumbe, dann wird i und j erhöht. du bist also plötzlich schon bei 1|1 statt 1|0. den rest der ersten zeile überspringste komplett usw.

und dann der schleifenkopf an sich: solange beide nicht die maximale dimension erreicht haben, mach weiter. selbst wenn du jetzt durch ne änderung zeile für zeile durchgehst, hört er nach der ersten auf - j is ja dann größer wie das maximum geworden.

solche matrizen gehste am besten mit ner doppelten for-schleife durch:

```
for(j = 0; j < COLUMNS; j++) {   // erst j durchgehn - spalte für spalte
    for(i = 0; i < ROWS; i++) { // dann i - zeile für zeile in einer spalte -> so wie man nen text liest ^^
        // vergleiche ersten buchstaben des suchwortes mit dem buchstaben an der matrix-position
        // wenn gleich - schau rundherum nach (die 8 angrenzenden felder - achtung ränder und ecken rausfiltern -> bei 0|0 gibts nur 3 bachbarn, bei 0|1 5 usw.), ob der 2. buchstabe des suchwortes gefunden wurde
        // hier am besten ne forschleife wieder bauen, die alle 8 drumherum kontrolliert (for k=0-7 bla) und die nicht existenten skipped
        // sollte hier irgendwo der 2. buchstabe gefunden werden, gehts in die nächste runde -> for(l=2 (die ersten beiden stimmen ja schon) bis suchwortlänge-1) schau, ob die folgenden buchstaben stimmen und brich ab, wenn was nich mehr übereinstimmt
        // is man aus der for-schleife wieder raus, gehts entweder weiter (das wort wurde noch nich gefunden - du bräuchtest irgend ne "flag" variable) bis alle 8 felder durch sin, oder er bricht nach nem fund komplett ab und gibt das ergebnis aus -> aktueller i und j wert is die gesuchte
    }
}
```

so könnte es prinzipiell funktionieren, denk ich mir. die letzte for schleife könntest vllt auch als while dann machen (while "string noch nich zu ende verglichen" oder "fehlerhafter vergleich") { vergleiche buchstaben } bla blubb.

hoffe, das hilft dir etwas


----------



## boss3D (8. November 2012)

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

Ich verstehe zwar jetzt, woran es scheitert, aber ich kann deinen Lösungsansatz nicht umsetzen. 

Eine "einfachere" Variante (oder vielleicht eh deine, nur anders formuliert) wäre es doch, in der ersten Hälfte des Code-Konstrukts nach dem Anfangsbuchstaben des eingegebenen Wortes zu suchen. Wird dieser gefunden, geht man in der Zeile um ein Feld weiter. So werden alle Zeilen durchgemacht.
Anschließend selbes Spiel in der zweiten Hälfte des Code-Konstrukts, nur hier spaltenweise. 

```
[COLOR=darkorange]for (i=0; i<ROWS; i++) { 
       [COLOR=darkorchid] for (j=0; j<COLUMNS; j++) {            if (*(string+i)==matrix[i][j]) {
                for (k=0; k<length; k++) {
                    printf("%c", *(string+k));
                }
                printf(" found horizontally! %d %d\n", i+1, j+1);
            [COLOR=darkorchid]} else if (*(string+j)==matrix[i][j]) { 
                for (k=0; k<length; k++) {
                    printf("%c", *(string+k));
                }
                printf(" found vertically! %d %d\n", i+1, j+1);
            }
        }    }
```
Wozu soll ich denn immer alle Felder rund um den Buchstaben kontrollieren? Schräg fällt sowieso weg und horizontal und vertikal kann ich doch, wie eben erklärt, aufspalten?! 

^^ Genau das probiere ich jetzt jedenfalls schon die ganze Zeit, nur ist noch nicht viel dabei rausgekommen (der Code oben stimmt natürlich noch nicht). Werde noch weiterprobieren ...

*[EDIT]*
Irgendwie so sollte es dann wohl für die Horizontalen ausschauen:

```
for (i=0; i<ROWS; i++) { 
        for (j=0; j<COLUMNS; j++) {
            if (*(string+i)==matrix[i][j]) {
                for (l=i; l<COLUMNS; l++) {
                    if (*(string+i)==matrix[i][l]) {
                        for (k=0; k<length; k++) {
                            printf("%c", *(string+k));
                        }
                        printf(" found horizontally! %d %d\n", i+1, j+1);
                    }
                }
            }
        }
    }
```
Ist noch nicht ganz richtig. ATM erkennt er schon die Position möglicher Startbuchstaben, gibt aber leider dann auch irgendwelche anderen von Buchstaben, die zwar im Wort enthalten, aber in der Matrix nicht direkt hinter dem Startbuchstaben sind, aus.  
*
[EDIT2]*
Da ich bei dem Problem im Gesamten nicht weiterkomme, habe ich jetzt mal versucht, nur für das Wort "SECURITY" in der ersten Zeile die richtige Ausgabe zu bekommen:

```
void searchMatrix(char *string, int matrix[][COLUMNS], int rows) {
    int i=0, j=0, k=0, count=0, length=0;

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

    for (j=0; j<COLUMNS; j++) {
        if (*(string+j)==matrix[i][j]) {
            count++;
            if (count==length) {
                for (k=0; k<length; k++) {
                    printf("%c", *(string+k));
                }
                printf(" found horizontally! %d %d\n", i+1, j+1);
            }
        }
    }
}
```
Allerdings gibt der leider mit dem Code gar nichts aus ...


----------



## boss3D (9. November 2012)

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

Okay, habe mir einen ganz neuen Ansatz ausgedacht ...

Da ich mit der ganzen Matrix überfordert bin, habe ich mir gedacht, ich spalte die Matrix einfach auf, indem ich aus jeder Zeile und jeder Spalte ein Feld mache und dann einfach den Feldinhalt mit dem Inhalt des eingegebenen Wortes vergleiche. Auf diese Weise habe ich zumindest schon mal die richtige Erkennung von Wörtern geschafft. Was noch nicht stimmt, ist die Ausgabe der Position des Startbuchstaben. Hier wäre Hilfe erwünscht. 

```
void searchMatrix(char *string, int matrix[][COLUMNS], int rows) {
    int i=0, j=0, length=0, [B][COLOR=royalblue]searchArrayOne[COLUMNS][/B], [B][COLOR=royalblue]searchArrayTwo[ROWS][/B];

   [B] [COLOR=royalblue]for (i=0; i<COLUMNS; i++) {[/B]
        [B][COLOR=royalblue]searchArrayOne[i]=matrix[0][i];[/B] [COLOR=seagreen]/* mache aus erster Zeile ein Feld */    [B][COLOR=royalblue]}
 [COLOR=royalblue]     for (j=0; j<ROWS; j++) {[/B]
        [B][COLOR=royalblue]searchArrayTwo[j]=matrix[j][0];[/B] [COLOR=seagreen]/* mache aus erster Spalte ein Feld */   [B][COLOR=royalblue] }[/B]

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

    for (i=0; i<COLUMNS; i++) {
        if (*(string+i)==searchArrayOne[i]) {
            continue;
        } else {
            for (j=0; j<length; j++) {
                printf("%c", *(string+j));
            }
            printf(" found horizontally! %d %d\n", 1, i);
            break;
        }
    }

    [COLOR=seagreen]/*
    for (j=0; j<ROWS; j++) {
        if (*(string+j)==searchArrayTwo[j]) {
            continue;
        } else {
            for (i=0; i<length; i++) {
                printf("%c", *(string+i));
            }
            printf(" found vertically! %d %d\n", 1, j);
            break;
        }
    }
    */}
```


----------



## DarkMo (9. November 2012)

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

asö, diagonalen fallen weg? und is die möglich richtung nur vor/runter oder auch rückwärts/hoch? nuja, verkürzt das ganze nur ebbes, aber  bleibt ja im grunde gleich ^^ ich probier mich ma "on the fly" am  problem. knifflig isses auf jeden fall nen bissl *g*


```
bool checkFind(int x, int y, int xDir, int yDir, char *searchString, int matrix[ROWS][COLUMNS]) { //  <- position des funds, offsets zur richtungsbestimmung und die eigentlichen daten
    bool found = true; // solange true, bis der erste (vergleichs-)fehler auftritt
    // for/while irgendwas hierhin
        if(*searchString+step+1 /* sofern step bei 0 beginnt, muss ich später noch genauer überegen ^^ */ == matrix[x+(xDir*step)][y+(yDir*step)]) { //  stimmt der 2. buchstabe des suchstrings mit dem nächsten (in  entsprechender richtung liegenden) feld-buchstaben der matrix überein
            // bla blubb ^^
        }
    return found;
}

void searchMatrix(char *searchString, int matrix[ROWS][COLUMNS]) { //  <- warum hast du da eigentlich sone seltsame variante? ^^
    int max = 2; // wieviele suchrichtungen soll es geben? atm geh ich mal von nur 2en aus (vorwärts und runter)
     for(y=0; y<COLUMNS; y++) { // <- erst spalten
        for(x=0; x<ROWS; x++) { // dann zeilen ^^ - zumindest find ichs persönlich so leichter nachvollziehbar (von der reihenfolge der abarbeitung her)
            if(*searchString==matrix[x][y]) { // erster buchstabe des suchstrings entspricht dem aktuell betrachteten zeichen in der matrix?
                for(i=0; i<max; i++) {
                    switch(i) { // für jede suchrichtung die fälle bearbeiten - leicht erweiterbar
                    case 0: { // suche nach rechts weiter
                        if(checkFind(x, y, 1, 0, searchString, matrix)) { // überprüfe den fund, ned das es nur zufällig der buchstabe war und der rest nich passt
                            printf("found string '%s' at position %d|%d in direction %d|%d.", searchString, x, y, 1, 0);
                            return; // und raus hier ^^
                        }
                        break;
                    }
                    case 1: { // suche nach unten weiter
                        if(checkFind(x, y, 0, 1, searchString, matrix)) {  // überprüfe den fund, ned das es nur zufällig der buchstabe war und  der rest nich passt
                            printf("found string '%s' at position %d|%d in direction %d|%d.", searchString, x, y, 0, 1);
                            return; // und raus hier ^^
                        }
                        break;
                    }
                    // hier könnte man jetz ganz easy weitere suchrichtungen anfügen...
                }
            }
        }
    }
}
```
k, will erstma fix mit family los, soweit bin ich jetz erstma gekommen. hab die endgültige suche mal in ne extra funke ausgelagert, so brauch man den kram ned für jede richtung seperat schreiben un brauch bei änderungen nur einmal was umschreiben. bei bis zu 8 möglichen suchrichtungen würde man sich sonst dusslig fixen ^^ denk ma, ich erweiter das später noch nen bissl


----------



## boss3D (9. November 2012)

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

^^ Okay, danke für die Mühe erstmal ...

Ich verstehe zwar, was du vor hast, aber die Umsetzung ist mir dann schon etwas zu hoch. Ich hätte es jetzt so probiert:


Spoiler





```
#include <stdio.h>
#include <stdlib.h>

#define ROWS 12
#define COLUMNS 12

int checkFind(int i, int j, int dir1, int dir2, char *string, int matrix[ROWS][COLUMNS]) {
    int x=0;

    for (x=1; x<=12; x++) {
        if (*(string+x) == matrix[i+(dir1*x)][j+(dir2*x)]) {
            return 0;
        } else {
            return 1;
        }
    }
}

int searchMatrix(char *string, int matrix[ROWS][COLUMNS]) {
    int i=0, j=0, h=0, k=0, length=0;

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

    for (i=0; i<COLUMNS; i++) {
        for (j=0; j<ROWS; j++) {
            if (*string==matrix[j][i]) {
                for (h=0; h<12; h++) {
                    switch (h) {
                        case 0: {
                            if (checkFind(i, j, 1, 0, string, matrix)==0) {
                                for (k=0; k<length; k++) {
                                    printf("%c", *(string+k));
                                }
                                printf(" found horizontally! %d %d\n", i+1, j+1);
                                return 0;
                            }
                            break;
                        }
                        case 1: {
                            if (checkFind(i, j, 0, 1, string, matrix)==0) {
                                for (k=0; k<length; k++) {
                                    printf("%c", *(string+k));
                                }
                                printf(" found vertically! %d %d\n", i+1, j+1);
                                return 0;
                            }
                            break;
                        }
                    }
                }
            }
        }
    }
}

void printMatrix(int matrix[ROWS][COLUMNS]) {
    int i=0, j=0;

    printf("\n+---+---+---+---+---+---+---+---+---+---+---+---+\n");
    for (i=0; i<ROWS; i++) {
        for (j=0; j<COLUMNS; j++) {
            printf("| %c ", matrix[i][j]);
            if (j==11) {
                printf("|\n+---+---+---+---+---+---+---+---+---+---+---+---+\n");
            }
        }
    }
}

int main(void) {
    int matrix[ROWS][COLUMNS] = {{'X', 'S', 'E', 'C', 'U', 'R', 'I', 'T', 'Y', 'C', 'O', 'T'},
                                 {'M', 'E', 'D', 'I', 'A', 'H', 'E', 'R', 'C', 'S', 'T', 'A'},
                                 {'K', 'C', 'F', 'X', 'J', 'A', 'E', 'S', 'I', 'I', 'L', 'S'},
                                 {'M', 'U', 'I', 'N', 'T', 'R', 'U', 'S', 'I', 'O', 'N', 'K'},
                                 {'A', 'R', 'R', 'Z', 'F', 'W', 'N', 'K', 'I', 'G', 'V', 'Z'},
                                 {'L', 'E', 'E', 'N', 'C', 'R', 'Y', 'P', 'T', 'I', 'O', 'N'},
                                 {'W', 'K', 'W', 'O', 'R', 'M', 'P', 'E', 'U', 'O', 'J', 'X'},
                                 {'A', 'V', 'A', 'M', 'D', 'N', 'D', 'P', 'J', 'H', 'A', 'L'},
                                 {'R', 'L', 'L', 'N', 'V', 'I', 'R', 'U', 'S', 'P', 'E', 'E'},
                                 {'E', 'W', 'L', 'D', 'D', 'E', 'X', 'O', 'L', 'T', 'P', 'U'},
                                 {'X', 'J', 'P', 'R', 'C', 'T', 'C', 'P', 'A', 'P', 'R', 'C'},
                                 {'G', 'K', 'B', 'U', 'F', 'F', 'E', 'R', 'S', 'L', 'T', 'B'}};
    int i=0;
    char string[13];

    printf("Matrix Search - Available commands:\n");
    printf("1 .. Enter a search string\n");
    printf("9 .. Print the matrix\n");
    printf("0 .. Quit the program\n");
    
    for ( ; ; ) { 
        printf("\nPlease enter your command: ");
        scanf("%d", &i);
        if (i==0) {
            exit(0);
        } else if (i==9) {
            printMatrix(matrix);
        } else if (i==1) {
            printf("Please enter search string: ");
            scanf("%s", &string);
            searchMatrix(string, matrix);
        }
    }

    return 0;
}
```



Allerdings kommt man damit auf keine vernünftige Ausgabe. Besonders kurios: Egal, was für einen blödsinnigen Code ich auch schreibe, oder in welcher Form ich deinen probiere, "SECURITY" wird immer gefunden (!), wenn auch an der falschen Position. Für sämtliche anderen enthaltenen Wörtern bekomme ich jedoch nicht einmal eine Ausgabe.   
*
[EDIT]*
Könnte man das Ganze nicht in auch so realisieren:

```
int searchMatrix(char *string, int matrix[ROWS][COLUMNS]) {
    int i=0, j=0, length=0;
    char searchString[]={0}, *coordinate;
    
    for (i=0; i!='\0'; i++) {
        searchString[i]=matrix[0][i]; [COLOR=seagreen]/* char array seachString bekommt Inhalt der ersten Matrix-Zeile */    }

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

    for (i=0; i<12; i++) {
        if (strstr(searchString, string) != NULL) {
            coordinate=strstr(searchString, string);
            for (j=0; j<length; j++) {
                printf("%c", *(string+j));
            }
            printf(" found horizontally! %d %d\n", *coordinate, i+1);
            break;
        } else {
            for (j=0; j<length; j++) {
                printf("%c", *(string+j));
            }
            printf(" not found!\n");
            break;
        }
    }
}
```
^^ Da könnte man ja dann auch eine Schleife basteln, die das char array searchString immer dann mit dem Inhalt einer weiteren Zeile/Spalte der Matrix befüllt, wenn in der vorhergehenden nichts gefunden wurde ...
BTW: Wieso gibt mir eigentlich der obige Code "SECURITY not found!" aus?


----------



## DarkMo (9. November 2012)

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

so, will ich ma versuchen, die erste funktion noch mit leben zu füllen...


```
bool checkFind(int x, int y, int xDir, int yDir, char *searchString, int matrix[ROWS][COLUMNS]) { //  <- position des funds, offsets zur richtungsbestimmung und die eigentlichen daten
    bool found = true; // solange true, bis der erste (vergleichs-)fehler auftritt
    int step = 2; // beginnend nach dem 2. buchstaben - der erste war der hauptfund, der 2. war der "richtungsfund"
    int searchX = 0, searchY = 0;
    while(*(searchString+step) != '\0') {
        searchX = x+(xDir*step);
        searchY = y+(yDir*step);
        if(searchX >= ROWS || searchY >= COLUMNS) { // wurde der rand der matrix erreicht, bevor das ganze wort gefunden wurde - abbruch
            found = false;
            break; // raus aus der while
        }
        if(*searchString+step != matrix[searchX][searchY]) { // stimmt der 2. buchstabe des suchstrings NICHT mit dem nächsten (in entsprechender richtung liegenden) feld-buchstaben der matrix überein -> abbrechen
            found = false;
            break; // raus aus der while
        }
        step = step + 1; // is ja kein c++ oder? jedenfalls gehts dann nen buchstaben weiter, wenn bisher alles passt
    }
    return found;
}

void searchMatrix(char *searchString, int matrix[ROWS][COLUMNS]) { //  <- warum hast du da eigentlich sone seltsame variante? ^^
    int max = 2; // wieviele suchrichtungen soll es geben? atm geh ich mal von nur 2en aus (vorwärts und runter)
     for(y=0; y<COLUMNS; y++) { // <- erst spalten
        for(x=0; x<ROWS; x++) { // dann zeilen ^^ - zumindest find ichs persönlich so leichter nachvollziehbar (von der reihenfolge der abarbeitung her)
            if(*searchString==matrix[x][y]) { // erster buchstabe des suchstrings entspricht dem aktuell betrachteten zeichen in der matrix?
                for(i=0; i<max; i++) {
                    switch(i) { // für jede suchrichtung die fälle bearbeiten - leicht erweiterbar
                    case 0: { // suche nach rechts weiter
                        if(checkFind(x, y, 1, 0, searchString, matrix)) { // überprüfe den fund, ned das es nur zufällig der buchstabe war und der rest nich passt
                            printf("found string '%s' at position %d|%d in direction %d|%d.", searchString, x, y, 1, 0);
                            return; // und raus hier ^^
                        }
                        break;
                    }
                    case 1: { // suche nach unten weiter
                        if(checkFind(x, y, 0, 1, searchString, matrix)) {  // überprüfe den fund, ned das es nur zufällig der buchstabe war und  der rest nich passt
                            printf("found string '%s' at position %d|%d in direction %d|%d.", searchString, x, y, 0, 1);
                            return; // und raus hier ^^
                        }
                        break;
                    }
                    // hier könnte man jetz ganz easy weitere suchrichtungen anfügen...
                }
            }
        }
    }
}
```

so, ok. ich GLAUBE so könnts gehen, wenn mir jetz keine denkfehler unterlaufen sind (oder rechtschreibfehler oder oder ^^). is halt jetz ohne ide oder so nur im textfenster geschrieben 

die hauptfunktion (unten) geht halt feld für feld der matrix durch (wie man ein buch liest - von links nach rechts und dann in die nächste zeile) und vergleicht den buchstaben darin mit dem ersten buchstaben des strings. findet er also bei "SECURITY" nen S irgendwo, so gehts in die nächste runde: er schaut die umliegenden felder durch (in dem bsp halt nur rechts und drunter, aber lässt sich ja simpel erweitern). findet er dort in einem der felder den 2. buchstaben (also in dem falle das E), so schickt er die position des S an die 2. funktion (die obere) die nun im endeffekt in der einmal gefundenen richtung (also immer weiter nach rechts oder immer weiter nach unten) die buchstaben vergleicht. findet er nun also den 3. buchstaben, is alles ok, findet er den 4. aber nich mehr, bricht er ab und gibt false zurück. dann würde die "äussere" funktion weitersuchen bis zum nächsten S oder eben bis zum ende.

falls die "innere" funktion ALLE buchstaben findet, dann gibts true zurück und er gibt eben den text aus, das ers wie wo was gefunden hat. so zumindest der plan. bei der inneren funktion mit dem step und xDir/yDir is hoffentlich klar, was er da macht. geht man beispielsweise nach rechts weiter, dann übergibt man ja den richtungs"vektor" 1|0 - also je 1 in x richtung und 0 in y richtung. in der checkFind schaut er dann also beim ersten vergleich (sagen wir, er hat bei 3|4 das S gefunden) bei searchX = 3 + (1 * 2) = 5 und searchY = 4 + (0 * 2) -> 5|4 nach dem 3. buchstaben. die 3 is S (der fundort), die 4 is E (die richtung) und die 5 is dann hoffentlich C. danach wird step um 1 erhöht, und er sucht bei searchX = 3 + (1 * 3) = 6 und searchY = 4 + (0 * 3) -> 6|4 nach dem 4. buchstaben. gut, ich hoffe, ich konnts dir verdeutlichen. is die matrix aber nur bis zur 6 (ROWS = 6) breit, dann würde er dann aber abbrechen, da 5 der maximale X-wert sein kann.

probiers mal aus, hoffe es funzt ^^


----------



## boss3D (9. November 2012)

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

Ich musste deinen Code minimalst anpassen, damit das Ganze kompilierbar ist. Semantisch sollte sich jedoch nichts geändert haben. Auf jeden Fall gibt's 2 Probleme: Erstens, der Code gibt für jedes x-beliebige Wort "gefunden" aus, und zweitens, bei tatsächlich existierenden Wörtern stimmen die Koordinaten nicht (außer bei SECURITY; da stimmt witzigerweise alles).


Spoiler





```
int checkFind(int x, int y, int xDir, int yDir, char *searchString, int matrix[ROWS][COLUMNS]) { 
    int found = 0; // solange true, bis der erste (vergleichs-)fehler auftritt
    int step = 2; // beginnend nach dem 2. buchstaben - der erste war der hauptfund, der 2. war der "richtungsfund"
    int searchX = 0, searchY = 0;
    while (*(searchString+step) != '\0') {
        searchX = x+(xDir*step);
        searchY = y+(yDir*step);
        if (searchX >= ROWS || searchY >= COLUMNS) { // wurde der rand der matrix erreicht, bevor das ganze wort gefunden wurde - abbruch
            found = 1;
            break; // raus aus der while
        }
        if (*(searchString+step) != matrix[searchX][searchY]) { // stimmt der 2. buchstabe des suchstrings NICHT mit dem nächsten (in entsprechender richtung liegenden) feld-buchstaben der matrix überein -> abbrechen
            found = 1;
            break; // raus aus der while
        }
        step++; // is ja kein c++ oder? jedenfalls gehts dann nen buchstaben weiter, wenn bisher alles passt
    }
    return found;
}

void searchMatrix(char *searchString, int matrix[ROWS][COLUMNS]) { //  <- warum hast du da eigentlich sone seltsame variante? ^^
    int x=0, y=0, i=0;
    
    int max = 2; // wieviele suchrichtungen soll es geben? atm geh ich mal von nur 2en aus (vorwärts und runter)
    
    for (y=0; y<COLUMNS; y++) { // <- erst spalten
        for (x=0; x<ROWS; x++) { // dann zeilen ^^ - zumindest find ichs persönlich so leichter nachvollziehbar (von der reihenfolge der abarbeitung her)
            if (*searchString==matrix[x][y]) { // erster buchstabe des suchstrings entspricht dem aktuell betrachteten zeichen in der matrix?
                for (i=0; i<max; i++) {
                    switch (i) { // für jede suchrichtung die fälle bearbeiten - leicht erweiterbar
                        case 0: { // suche nach rechts weiter
                            if (checkFind(x, y, 1, 0, searchString, matrix)) { // überprüfe den fund, ned das es nur zufällig der buchstabe war und der rest nich passt
                                printf("found string '%s' at position %d|%d", searchString, x+1, y+1);
                                return; // und raus hier ^^
                            }
                            break;
                        }
                        case 1: { // suche nach unten weiter
                            if (checkFind(x, y, 0, 1, searchString, matrix)) {  // überprüfe den fund, ned das es nur zufällig der buchstabe war und  der rest nich passt
                                printf("found string '%s' at position %d|%d", searchString, x+1, y+1);
                                return; // und raus hier ^^
                            }
                            break;
                        }
                    // hier könnte man jetz ganz easy weitere suchrichtungen anfügen...
                    }
                }
            }
        }
    }
}
```



Vielen Dank, in jedem Fall, für die Mühe! Ich weiß deine Hilfe echt zu schätzen, aber ganz glücklich bin ich mit der Lösung trotzdem nicht. Auf der einen Seite, weil ich nicht selber darauf gekommen bin und auf der anderen Seite, weil ich das vermutlich selber auch nicht nachbauen könnte. 

Wenn es dir also nichts ausmacht, würde ich gerne versuchen, mit deiner Hilfe den Weg, den ich im EDIT in meinem vorigen Posting beschrieben habe, weiterzugehen und zu schauen, ob das auch irgendwann zu einem funktionierenden Code führt.


----------



## DarkMo (10. November 2012)

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

sicher sicher, kann ich nur zu gut verstehen ^^ bringt ja nix, wenn man "hirnlos" kopiert, man muss es ja auch verstehen und anwenden können. und da hilft selber tüfteln und fummeln immer viel.

ps: hab ich wohl unbewusst auf security optimiert wa? xD


----------



## boss3D (10. November 2012)

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

^^ LOL, ja, SECURITY hat er bei meinen Varianten auch immer gefunden, aber sonst nichts ... 
-----------------------

Bei meinem jetzigen Ansatz verzichte ich erstmal auf zu viel selbstgeschriebenen Code zu verzichten und versuche, die zentralen Dinge durch *fertige Funktionen* zu erledigen. Erst, wenn so alles funktioniert, möchte ich diese nach und nach durch selbstgeschriebenen Code ersetzen. 

```
void searchMatrix(char *string, int matrix[ROWS][COLUMNS]) {
    int i=0, j=0, k=0, l=0, length=0;
    char searchString[13], [COLOR=royalblue][B]*coordinate[/B];
    
    while (*(string+length)!='\0') {
        length++;
    }

    while (i<ROWS) { [COLOR=seagreen]/* durchsuche jedes Feld, beginnend beim ersten, horizontal*/        for (j=0; j<COLUMNS; j++) {
            searchString[j]=matrix[i][j]; 
        }
        if ([COLOR=darkorchid][B]strstr[/B](searchString, string) != NULL) {
            [COLOR=royalblue][B]coordinate=strstr(searchString, string);[/B]            printf("%s found horizontally! %d %d\n", string, i+1, [COLOR=royalblue][B](*coordinate)+1[/B]); [COLOR=seagreen]/* wenn Wort gefunden, ... */            break; [COLOR=seagreen]/* ... verlasse Schleife */        } else { [COLOR=seagreen]/* sonst ... */            i++; [COLOR=seagreen]/* springe in die nächste Zeile und suche wieder */            if (i==12) { [COLOR=seagreen]/* wenn alle Zeile erfolglos durchsucht wurden, ... */                while (k<COLUMNS) { [COLOR=seagreen]/* selbes Spiel mit den Spalten */                    for (l=0; l<ROWS; l++) {
                        searchString[l]=matrix[l][k];
                    }
                    if ([B][COLOR=darkorchid]strstr[/B](searchString, string) != NULL) {
                        [COLOR=royalblue][B]coordinate=strstr(searchString, string);[/B]                        printf("%s found vertically! %d %d\n", string, [COLOR=royalblue][B](*coordinate)+1[/B], k+1));
                        break;
                    } else { [COLOR=seagreen]/* wurde Wort auch in Spalten nicht gefunden, ... */                        k++;
                        if (k==12) {
                            printf("%s not found!\n", string); [COLOR=seagreen]/* existiert es nicht in der Matrix */                            break;
                        }
                    }
                }
            }
        }
    }
}
```
Die Suche funktioniert und stimmt bereits für sämtliche Zeilen und Spalten der Matrix (), nur leider gibt er noch völlig falsche Spalten-Koordinaten bei horizontal und falsche Zeile-Koordinaten bei vertikal gefundenen Wörtern aus. 

Das liegt jetzt wohl an einer falschen Anwendung des *Pointers von strstr*, der ja nach meinem Verständnis auf den Feldindex des ersten Buchstaben des gefundenen Wortes zeigt. Kennst du dich mit der genauen Arbeitsweise von strstr aus? Wie genau lasse ich den Speicherinhalt des Pointers bei gefundenen Wörtern als die jeweilige Koordinate ausgeben?

*[EDIT]*
Ich habe mir jetzt testweise mal eine Hilfsfunktion zur Ermittlung der jeweiligen Zeilenkoordinate bei Spalten-Wörtern bzw. der jeweiligen Spaltenkoordinate bei Zeilen-Wörtern geschrieben, allerdings liefert die immer -52 und ich komme nicht darauf, warum ...

```
int checkPosition(char *string1, char *string2) {
    int i=0, result=0, length=0, count=0;

    while (*(string2+length)!='\0') { /* ermittle die Länge des zu suchenden Wortes */
        length++;
    }

    while (*(string1+i)!='\0' || *(string2+i)!='\0') { 
        if (*(string2+i)==*(string1+i)) { [COLOR=seagreen]/* vergleiche beide char strings buchstabenweise */            count++; [COLOR=seagreen]/* erhöhe Zähler bei Übereinstimmung */            if (count==length) { [COLOR=seagreen]/* sobald Zähler der Länge entspricht, ... */                [COLOR=royalblue][B]result=*(string2+(i-(length-1)));[/B] [COLOR=seagreen]/* ... berechne die Position des ersten Buchstabens des Suchwortes im Such-Feld */                return result;
            }
        }
        i++;
    }
}
```
^^ So müsste ich doch eigentlich die gewünschte Koordinate bekommen, oder?

Hier noch der derzeitig gesamte Code:


Spoiler





```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define ROWS 12
#define COLUMNS 12

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

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

    return length;
}

int checkPosition(char *string1, char *string2) {
    int i=0, result=0, length=checkLength(string2), count=0;

    while (*(string1+i)!='\0' || *(string2+i)!='\0') {
        if (*(string2+i)==*(string1+i)) {
            count++;
            if (count==length) {
                result=*(string2+(i-(length-1)));
                return result;
            }
        }
        i++;
    }
}

void searchMatrix(char *string, int matrix[ROWS][COLUMNS]) {
    int i=0, j=0, k=0, l=0, length=checkLength(string);
    char searchString[13];

    while (i<ROWS) {
        for (j=0; j<COLUMNS; j++) {
            searchString[j]=matrix[i][j]; 
        }
        if (strstr(searchString, string) != 0) {
            printf("%s found horizontally! %d %d\n", string, i+1, checkPosition(searchString, string));
            break;
        } else {
            i++;
            if (i==12) {
                while (k<COLUMNS) {
                    for (l=0; l<ROWS; l++) {
                        searchString[l]=matrix[l][k];
                    }
                    if (strstr(searchString, string) != NULL) {
                        printf("%s found vertically! %d %d\n", string, checkPosition(searchString, string), k+1);
                        break;
                    } else {
                        k++;
                        if (k==12) {
                            printf("%s not found!\n", string);
                            break;
                        }
                    }
                }
            }
        }
    }
}

void printMatrix(int matrix[ROWS][COLUMNS]) {
    int i=0, j=0;

    printf("\n+---+---+---+---+---+---+---+---+---+---+---+---+\n");
    for (i=0; i<ROWS; i++) {
        for (j=0; j<COLUMNS; j++) {
            printf("| %c ", matrix[i][j]);
            if (j==11) {
                printf("|\n+---+---+---+---+---+---+---+---+---+---+---+---+\n");
            }
        }
    }
}

int main(void) {
    int matrix[ROWS][COLUMNS] = {{'X', 'S', 'E', 'C', 'U', 'R', 'I', 'T', 'Y', 'C', 'O', 'T'},
                                 {'M', 'E', 'D', 'I', 'A', 'H', 'E', 'R', 'C', 'S', 'T', 'A'},
                                 {'K', 'C', 'F', 'X', 'J', 'A', 'E', 'S', 'I', 'I', 'L', 'S'},
                                 {'M', 'U', 'I', 'N', 'T', 'R', 'U', 'S', 'I', 'O', 'N', 'K'},
                                 {'A', 'R', 'R', 'Z', 'F', 'W', 'N', 'K', 'I', 'G', 'V', 'Z'},
                                 {'L', 'E', 'E', 'N', 'C', 'R', 'Y', 'P', 'T', 'I', 'O', 'N'},
                                 {'W', 'K', 'W', 'O', 'R', 'M', 'P', 'E', 'U', 'O', 'J', 'X'},
                                 {'A', 'V', 'A', 'M', 'D', 'N', 'D', 'P', 'J', 'H', 'A', 'L'},
                                 {'R', 'L', 'L', 'N', 'V', 'I', 'R', 'U', 'S', 'P', 'E', 'E'},
                                 {'E', 'W', 'L', 'D', 'D', 'E', 'X', 'O', 'L', 'T', 'P', 'U'},
                                 {'X', 'J', 'P', 'R', 'C', 'T', 'C', 'P', 'A', 'P', 'R', 'C'},
                                 {'G', 'K', 'B', 'U', 'F', 'F', 'E', 'R', 'S', 'L', 'T', 'B'}};
    int i=0;
    char string[13];

    printf("Matrix Search - Available commands:\n");
    printf("1 .. Enter a search string\n");
    printf("9 .. Print the matrix\n");
    printf("0 .. Quit the program\n");
    
    for ( ; ; ) { 
        printf("\nPlease enter your command: ");
        scanf("%d", &i);
        if (i==0) {
            exit(0);
        } else if (i==9) {
            printMatrix(matrix);
        } else if (i==1) {
            printf("Please enter search string: ");
            scanf("%s", &string);
            searchMatrix(string, matrix);
        }
    }

    return 0;
}
```


----------



## DarkMo (10. November 2012)

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

mach dir doch wegen der koords nich sonen stress ^^ also bei meinem bsp zum beispiel geht das doch sehr simpel: er geht ja feld für feld durch, hat daher doch schon die koords vom jeweiligen buchstaben. findet er nun also das S bei 0|2 (glaub da wars bei deiner bsp-matrix), dann hat er ja genau diese x|y coord in dem moment. eben jene 0|2. für die suche in den umliegenden feldern, nutzt er ja ne komplett neue variable, x|y bleiben unberührt. findet er da nun irgendwo das E, gehen auch x und y, also 0|2 in die checkFind funke rein un ned die koordinate vom E. um dann nach dem C zu suchen, fängt step in checkFind ja bei 2 an. checkFind muss also nur prüfen, ob in der eingeschlagenen richtung das ganze wort zu finden is. das is dann der fall, wenn jeder einzelne buchstabe des suchworts in der richtung gefunden wird und die grenzen der matrix nich gesprengt werden. ein "fehler" is mir da im übrigen noch unterlaufen - ich prüfe nur, ob searchX und searchY über das maximum hnauslaufen, nich aber übers minimum. das wäre in dem fall wichtig, wo man auch nach links oder oben bspw suchen lässt. in dem einfachen falle is das aber kein problem.

gut, checkFind findet also das ganze wort und schmeisst true zurück, die if-bedingung in searchMatrix is erfüllt und er kann ganz simpel x|y ausgeben (so wie ich das im bsp auch schon gemacht hab - siehe mein printf).


----------



## boss3D (10. November 2012)

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

^^ Fast genauso arbeitet ja meine Funktion checkPosition() auch?! Die schaut, ob alle gesuchten Buchstaben schön nebeneinander stehen und geht dabei bis zum letzten durch. Von dem zieht sie dann die Länge-1 des Suchwortes ab und müsste somit genau beim Startbuchstaben landen. 

Ich sehe da jetzt nicht den großen Unterschied zu deiner Version, außer, dass es bei dir anscheinend funktioniert ...

Beziehungsweise, wenn ich die Funktion so umschreibe, müsste sie genau das selbe machen, wie deine:

```
int checkPosition(char *string1, char *string2) {
    int i=0, result=0, length=checkLength(string2), count=0;

    while (*(string1+i)!='\0' || *(string2+i)!='\0') { [COLOR=seagreen]/* solange der kürzere String (logischerweise das Suchwort) nicht vollständig durchlaufen ist ... */        if (*(string2+i)==*(string1+i)) { [COLOR=seagreen]/* ... vergleiche das Suchwort und die Zeile/Spalte buchstabenweise */            count++; [COLOR=seagreen]/* bei Übereinstimmung erhöhe den Zähler */            if (count==length) { [COLOR=seagreen]/* entspricht der Zähler irgendwann der Wortlänge, stehe alle richtigen Buchstaben nebeneinander */                return (*(string2)); [COLOR=seagreen]/* gib daher den Index des Anfangsbuchstabens des Suchwortes zurück */            }
        }
        i++;
    }
}
```
^^ Gibt aber auch nicht den richtigen Wert zurück. Da bekomme ich immer Werte im Bereich von 88 bis 60. Würde mich interessieren, wo das herkommt.


----------



## DarkMo (10. November 2012)

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

kurze verständnisfrage dazu nochmal:
du übergibst einmal das zu suchende wort (SECURITY = string1) und einmal die zeile/spalte der matrix? fängt die dabei erst beim S an oder is das die komplette spalte/zeile die übergeben wird?

gut, jetz zum eigentlichen problem:
return (*(string2));

zum einen - die klammern kannste weglassen ^^ zum anderen, was macht denn *string2? haste selber schon oft verwendet ^^ das liefert nich den index zurück, sondern das erste zeichen des strings. und dieses zeichen ist ein char. nun ist der returnwert der funktion aber int. ergo wird das ganze konvertiert zu einem int-wert. und wie casted man ein char zu einem int? ^^ ich sage nur ascii-wert. das S hat zum bsp den wert... 83. würdest du da nen string (also nen "echten" und nich das char*) zurückgeben wollen, würd er dann sicherlich meckern. er meckert hier nur nich, weil es halt kein problem is, nen char auf int zu casten (eben, weil er dann den entsprechenden ascii wert des zeichens angibt. andersrum gehts freilich aus int -> char).

du müsstest also die aktuelle matrix position kennen (vom letzten buchstaben) und dann die länge davon abziehen. und um die zu kennen, musst du sie wohl irgendwie mit übergeben. und genau das mach ich ja bei meiner funktion ^^ aber: wenn ich die anfangsposition übergebe - brauch ich sie am ende doch garnich zu berechnen ^^


----------



## boss3D (11. November 2012)

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

string1 = Die gesamte Zeile bzw. die gesamte Spalte von Feld 0 bis 11
string2 = Suchwort

Das Problem sehe ich jetzt, danke, nur kann ich leider keinen Startwert mitübergeben, weil ich aus strstr keinen Startwert rausbekomme. Die Funktion überprüft ja nur, ob der eine string im anderen drinnen steckt, aber nicht, wo genau. 
Auf den Startwert muss die Funktion checkPosition von selbst kommen und daran arbeite ich jetzt noch. --> Dass eben z.B. bei SECURITY nicht der ASCII Wert von S, sondern 2 als Position von S zurückgegeben wird.

*[EDIT]*
So komme ich der Sache anscheinend schon sehr nahe:

```
int checkPosition(char *string1, char *string2) {
    int i=0, j=0, result=0, length=checkLength(string2), count1=0, count2=0;

    while (*(string1+i)!='\0' || *(string2+i)!='\0') {
        if (*(string2+i)==*(string1+i)) {
            count1++;
            if (count1==length) { [COLOR=seagreen]/*  wenn der eine string im anderen drinnensteckt ... */                if (*(string2+j) != *(string1+j)) { [COLOR=seagreen]/* ...  und der erste Buchstabe des Suchwortes nicht zufällig auch der erste Buchstabe der Zeile/Spalte ist, ... */                    while (*(string1+j++) != *(string2+j)) { [COLOR=seagreen]/* ... gehe so viele Index-Felder weiter, bis eine Übereinstimmung mit dem Anfangsbuchstaben gefunden wurden. */                        count2++; [COLOR=seagreen]/* erhöhe dabei für jedes weitergesprungene Index-Feld den Zähler2 */                    }
                    return count2; [COLOR=seagreen]/* liefere den Wert von Zähler2, der nun die Koordinate des Anfangsbuchstaben des Suchwortes enthält, zurück */                } else { [COLOR=seagreen]/* wenn zufälligerweise sofort im erste Feldindex eine Übereinstimmung gefunden wird ... */                    j=1;
                    return j; [COLOR=seagreen]/* gib 1 zurück */                }
            }
        }
        i++;
    }
}
```
Manche Koordinaten (z.B. für MALWARE) stimmen schon, aber noch nicht alle ...

Wie kann das sein, dass der selbe Code für ein Wort stimmt und für alle anderen nicht???


----------



## DarkMo (11. November 2012)

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

ich glaub ich weis worans liegt:
while(*(string1+j*++*) != *(string2*+j*)) count2++;

also dieser innere durchgang zum rausfinden der position. als ich das grad abschrieb, fiel mir noch das dick-unterstrichene auf ^^ du hast da nen ++ hinterm j. copy-paste überbleibsel? ^^ soll so glaube nich da stehn oder?  naja, der hauptfehler den ich meinte is das +j hinterm string2. du willst doch schauen, ob eines der felder der matrix-zeile mit dem ersten des suchstrings übereinstimmt. du musst also den matrix-string zeichen für zeichen durchgehen (+j) und dabei immer mit dem selben zeichen (dem ersten) des suchstrings vergleichen. das +j beim string2 muss also weg.

die grundidee passt erstmal, aber schau dir mal folgende beispielmatrixzeile an:
XGSPSECURITYDRF
was passiert denn hier? security startet bei index 4, bei index 2 is aber auch nen S... ^^ daher hatte ich diese prüfung bei mir quasi in 3 schritten gebaut. er schaut erst, ob er ein S findet, dann schaut er, ob er angrenzend ein E findet (was erst beim 2. S der fall is) und dann schaut er vom fundort des 2. S ausgehend in richtung des dort benachbart gefundenen E's, ob er auch noch CURITY findet.


----------



## boss3D (11. November 2012)

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

^^ Doch, die Zeile war genau so beabsichtigt, wie du sie noch einmal angeführt hast. string1 ist ja das lange Feld in dem gesucht wird und unter der Annahme, dass der Startbuchstabe des zu suchenden Wortes nicht gleich am Anfang steht, muss eben ein paar Mal weitergesprungen werden. Das darf allerdings nicht auch im Suchwort (= string2) passieren, weil ja sonst nicht mehr nach S gesucht werden würde. Deswegen bleibt das j dort konstant auf 0. 
+0 klingt vielleicht komisch, allerdings kommt ohne ein noch größerer Blödsinn raus, also wird's nicht so falsch sein. 

Ich versuche jetzt noch, den Code entsprechend deiner Idee zu erweitern, allerdings kann ich nicht einfach deinen Part übernehmen, weil das dann nicht mehr zum Rest meiner Version passen würde. Außerdem will ich's ja, mit Hilfe, selber schaffen ... 

BTW: Genau wegen dem Problem, ob auch die nachfolgenden Buchstaben stimmen, war ja mein ursprünglicher Ansatz, das lange Feld bis zum letzten Buchstaben des Suchwortes zu druchlaufen und dann über die Wortlänge auf den ersten runterzurechnen. Ich glaube, da werde ich weitermachen.


----------



## DarkMo (11. November 2012)

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

achso, das soll gleich der increment fürs j sein? mach das lieber einzeln. wenn ich jetz nich völlig falsch liege, wird einerseits das j++ am anfang der rechnung ausgeführt (a=1+2 rechnet er glaube 2+1=3), so dass du nie den 0er index vergleichst (gut, wäre in dem falle glaube sogar zu verschmerzen) und andrerseits - viel wichtiger: mit j++ erhöhst du j. also auch das von string2+j! wenn du da sowas wie string2+0 stehen haben willst - dann lass die variable doch auch einfach weg >< um den ersten buchstaben von string2 zu erhalten, reicht nunmal ein einfaches *string2.

in dem bsp von mir (XGSPSECURITYDRF/SECURITY) vergleichst du im ersten durchlauf also G mit E (XGSPSECURITYDRF/SECURITY), dann S mit C usw usf. dass KANN nix werden ^^


----------



## boss3D (11. November 2012)

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

Ja, das hätte das Inkrement sein sollen. Wenn ich das aus dem Schleifenkopf rausnehme und sonst wo in der Schleife reinschreibe, erhöht es ja wieder beide j gleichermaßen und das wollte ich verhindern. Ganz offensichtlich macht es auch einen Unterschied, ob nur *string2, oder *(string2+j) mit j=0 dasteht, weil ja auch die Ausgabe damit eine andere ist. Warum, erschließt sich mir allerdings auch nicht. 

Bei deinem Bsp komme ich nicht mit. Meine Funktion sucht doch zuerst einmal das S (wäre bei dir der dritte Buchstabe) und fängt erst dann zum Vergleichen an. Somit --> P == E? ... S == C? ...

------------------------------
Wie gesagt, ich probiere jetzt wieder meinen ursprünglichen Ansatz. Dann fängt die Rechnerei nämlich erst an, wenn ich schon weiß, dass die richtigen Buchstaben direkt hintereinander stehen. Dann einfach über die Wortlänge auf das richtige S runterrechnen, sollte kein Problem sein. 

PS: Hier noch einmal die Matrix zum Nachschauen:


Spoiler





```
int matrix[ROWS][COLUMNS] = {{'X', [COLOR=royalblue]'S', 'E', 'C', 'U', 'R', 'I', 'T', 'Y', 'C', 'O', 'T'},
                             {'M', 'E', 'D', 'I', 'A', 'H', 'E', 'R', 'C', 'S', 'T', 'A'},
                             {'K', 'C', [COLOR=royalblue]'F', 'X', 'J', 'A', 'E', 'S', 'I', 'I', 'L', 'S'},
                             {[COLOR=royalblue]'M', 'U', [COLOR=royalblue]'I', 'N', 'T', 'R', 'U', 'S', 'I', 'O', 'N', 'K'},
                             {[COLOR=royalblue]'A', 'R', [COLOR=royalblue]'R', 'Z', 'F', 'W', 'N', 'K', 'I', 'G', 'V', 'Z'},
                             {[COLOR=royalblue]'L', 'E', [COLOR=royalblue]'E', 'N', 'C', 'R', 'Y', 'P', 'T', 'I', 'O', 'N'},
                             {[COLOR=royalblue]'W', 'K', [COLOR=royalblue]'W', 'O', 'R', 'M', 'P', 'E', 'U', 'O', 'J', 'X'},
                             {[COLOR=royalblue]'A', 'V', [COLOR=royalblue]'A', 'M', 'D', 'N', 'D', 'P', 'J', 'H', 'A', 'L'},
                             {[COLOR=royalblue]'R', 'L', [COLOR=royalblue]'L', 'N', [COLOR=royalblue]'V', 'I', 'R', 'U', 'S', 'P', 'E', 'E'},
                             {[COLOR=royalblue]'E', 'W', [COLOR=royalblue]'L', 'D', 'D', 'E', 'X', 'O', 'L', 'T', 'P', 'U'},
                             {'X', 'J', 'P', 'R', 'C', 'T', 'C', 'P', 'A', 'P', 'R', 'C'},
                             {'G', 'K', [COLOR=royalblue]'B', 'U', 'F', 'F', 'E', 'R', 'S', 'L', 'T', 'B'}};
```



*[EDIT]*
(Fast) geschafft!!! 

```
int checkPosition(char *string1, char *string2) {
    int i=0, j=0, k=0, result=0, length=checkLength(string2), count1=0, count2=0;

    while (*(string1+i)!='\0' || *(string2+i)!='\0') {
        if (*(string2+i) != *(string1+i)) {
            count1++;
            j=i;
            if (*(string2+k) == *(string1+j)) {
                j++;
                k++;
                count2++;
                if (count2==length) {
                    [COLOR=royalblue][B]result=count1-(length-1);[/B]                    return result;
                }
            }
        }
        i++;
    }
}
```



			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



^^ Wieso stimmen jetzt eigentlich sämtliche Koordinaten, nur bei MALWARE kommt so ein komischer Wert raus?


----------



## DarkMo (11. November 2012)

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

so, dank geht an meinen sohn, jetz darf ich alles nochma versuchen zu schreiben -.- kA wie der das immer schafft. der rennt am laptop vorbei und ff geht aus... mitten im text *kotz*



boss3D schrieb:


> Wenn ich das aus dem Schleifenkopf rausnehme und sonst wo in der Schleife reinschreibe, erhöht es ja wieder beide j gleichermaßen und das wollte ich verhindern.


 das wollt ich dir ja eben schon schreiben: auch in der schleife führt er das ding aus. wenn du also bei string1 das j inkrementierst, hat es beim string2 vergleich schon den erhöhten wert. diese funktionalität nutzte ich bei meinem bsp ja auch schon, als ich if(checkFind...) schrieb. er führt dann die checkFind funktion aus und die liefert je nachdem entweder true oder false zurück und danach entscheidet dann die if-bedingung, welcher weg gegangen wird.

gehn wir mal deinen code hier stück für stück durch (das würd ich eh immer empfehlen, dass mal zu machen. sicher nich für 100000 daten, aber so für 5-10 kann mans mal probieren ^^):

```
in die funktion geht nun also rein: string1 = XSECURITYCOT und string2 = SECURITY. das wäre die ausgangslage.
    solange nun also weder das zeichen bei *string1+i, noch bei *string2+i \0 ist, fahre fort. -> in unsrem fall ist i=0 und die anfangsbuchstaben sind X und S - die sind nicht \0 - weiter.
        [COLOR=red]*wenn jetzt *string1+i nicht das selbe wie *string2+i ist, mache weiter. wir sind noch bei X und S - die gleichen sich nicht, weiter gehts also.
            wir erhöhen count auf 1,
            j bekommt den wert von i, wird also 0
            ... hier kann man doch eigentlich schon abbrechen ^^
```
also pass auf: erstmal willst du doch bei * rausfinden, ob der erste buchstabe des suchstrings (string2) mit dem buchstaben an der aktuellen position im string1 übereinstimmt oder? du schiebst doch aber den vergleichsbuchstaben von string2 schonwieder gleichmäßig durch i durch die gegend ^^ sprich, wenn er das erste ding durch hat, dann sucht er bei string1+1 (erster durchlauf +0) -> S und vergleicht das mit string2+1 -> E. du willst doch aber sicher auch hier wieder das S von string2 zum vergleich heranziehen oder?

und dann is die ganze grundstruktur im eimer  du sagst quasi "solange der erste buchstabe noch nich gefunden wurde, erhöhe den zähler1 (soweit so gut) und suche dann die restlichen buchstaben des suchwortes" oO wenn er den anfang noch garnich gefunden hat, wie kann er dann den rest vergleichen? ^^ die struktur muss also ganz anders aussehen:

```
while(beide nich zuende)
    if(*str1+i != *str2) erhöhe den zähler // hier wurds ja nich gefunden
    else vergleiche den restlichen teil // hier wurde ja der anfang gefunden, jetzt kann man auch vergleichen
```
jo, und da im else teil, da muss quasi dann der part rein, wo ich da oben aufgehört hatte. hier musst du jetzt auch str2 weiterschieben, weil du willst ja wissen, ob auch die anderen buchstaben in str1 folgen oder nich.

edit: was mich viel eher wundert is, dass da überhaupt irgendwas stimmt xD


----------



## boss3D (11. November 2012)

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

Während dein Sohn "gezaubert" hat, habe ich fleißig editiert ...  

Wir müssten eigentlich nur mehr die kuriose Ausgabe für MALWARE klären (siehe voriges Posting), den Rest habe ich während deines FF-Aussetzers erledigt. 

*[EDIT]*
Kann es sein, dass ich bei MALWARE irgendwie über die Feldgrenzen rauskomme? Sollte doch eigentlich durch den '\0'-Check verhindert werden?!


----------



## DarkMo (11. November 2012)

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

kam jetz zwar nich nochma dazu, mich intensiver mit deiner version zu befassen (müsst eigentlich scho im nest sein ><), aber mich hatte die lust gepackt es mal selbst zu bauen. das kam bei raus:


```
#include <stdio.h>
#include <tchar.h>

#define ROWS    12
#define COLUMNS    12

int matrix[ROWS][COLUMNS] = {{'X', 'M', 'K', 'M', 'A', 'L', 'W', 'A', 'R', 'E', 'X', 'G'},
                             {'S', 'E', 'C', 'U', 'R', 'E', 'K', 'V', 'L', 'W', 'J', 'K'},
                             {'E', 'D', 'F', 'I', 'R', 'E', 'W', 'A', 'L', 'L', 'P', 'B'},
                             {'C', 'I', 'X', 'N', 'Z', 'N', 'O', 'M', 'N', 'D', 'R', 'U'},
                             {'U', 'A', 'J', 'T', 'F', 'C', 'R', 'D', 'V', 'D', 'C', 'F'},
                             {'R', 'H', 'A', 'R', 'W', 'R', 'M', 'N', 'I', 'E', 'T', 'F'},
                             {'I', 'E', 'E', 'U', 'N', 'Y', 'P', 'D', 'R', 'X', 'C', 'E'},
                             {'T', 'R', 'S', 'S', 'K', 'P', 'E', 'P', 'U', 'O', 'P', 'R'},
                             {'Y', 'C', 'I', 'I', 'I', 'T', 'U', 'J', 'S', 'L', 'A', 'S'},
                             {'C', 'S', 'I', 'O', 'G', 'I', 'O', 'H', 'P', 'T', 'P', 'L'},
                             {'O', 'T', 'L', 'N', 'V', 'O', 'J', 'A', 'E', 'P', 'R', 'T'},
                             {'T', 'A', 'S', 'K', 'Z', 'N', 'X', 'L', 'E', 'U', 'C', 'B'}};

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

void printMatrix(int x, int y, int xDir, int yDir, int strLen) {
    int i, j, k;
    bool isPart;

    for(i = 0; i <= ROWS; i++) printf("+-----");
    printf("+\n");
    for(i = 0; i <= ROWS; i++) {
        if(i == 0) printf("| x\\y ");
        else if(i <= 10) printf("|  %d  ", i - 1);
        else printf("|  %d ", i - 1);
    }
    printf("|\n");
    for(i = 0; i <= ROWS; i++) printf("+=====");
    printf("+\n");
    for(j = 0; j < COLUMNS; j++) {
        for(i = 0; i <= ROWS; i++) {
            if(i == 0) {
                if(j < 10) printf("|  %d |", j);
                else  printf("| %d |", j);
            } else if(strLen > 0) {
                if(x == i-1 && y == j) printf("| [%c] ", matrix[i - 1][j]);
                else {
                    isPart = false;
                    for(k = 0; k < strLen; k++) {
                        if((x + (k * xDir)) == i-1 && (y + (k * yDir)) == j) {
                            printf("| (%c) ", matrix[i - 1][j]);
                            isPart = true;
                        }
                    }
                    if(!isPart) printf("|  %c  ", matrix[i - 1][j]);
                }
            } else printf("|  %c  ", matrix[i - 1][j]);
        }
        printf("|\n");
        for(i = 0; i <= ROWS; i++) printf("+-----");
        printf("+\n");
    }
}

// Position des Funds, Offsets zur Richtungsbestimmung und die eigentlichen Daten -> sucht detailliert nach dem vermeindlich gefundenen Wort
bool checkFind(int x, int y, int xDir, int yDir, char *searchString) {
    bool found = true; // solange true, bis der erste (vergleichs-)fehler auftritt
    int step = 2; // beginnend nach dem 2. buchstaben - der erste war der hauptfund, der 2. war der "richtungsfund"
    int searchX = 0, searchY = 0;
    while(*(searchString+step) != '\0') {
        searchX = x+(xDir*step);
        searchY = y+(yDir*step);
        if(searchX >= ROWS || searchY >= COLUMNS || searchX < 0 || searchY < 0) { // wurde der rand der matrix erreicht, bevor das ganze wort gefunden wurde? - abbruch
            found = false;
            break; // raus aus der while
        }
        if(*(searchString+step) != (char)matrix[searchX][searchY]) { // stimmt der nächste buchstabe des suchstrings NICHT mit dem nächsten (in entsprechender richtung liegenden) feld-buchstaben der matrix überein? -> abbrechen
            found = false;
            break; // raus aus der while
        }
        step = step + 1; // is ja kein c++ oder? jedenfalls gehts dann nen buchstaben weiter, wenn bisher alles passt
    }
    return found;
}

// durchsucht die Matrix nach den ersten Hinweisen auf das gesuchte Wort
void searchMatrix(char *searchString) {
    int maxDir = 8; // wieviele suchrichtungen soll es geben? atm geh ich mal von nur 2en aus (vorwärts und runter)
    int x, y, i;
    for(y = 0; y < COLUMNS; y++) { // <- erst spalten
        for(x = 0; x < ROWS; x++) { // dann zeilen
            if(*searchString == (char)matrix[x][y]) { // erster buchstabe des suchstrings entspricht dem aktuell betrachteten zeichen in der matrix?
                for(i = 0; i < maxDir; i++) {
                    switch(i) { // für jede suchrichtung die fälle bearbeiten - leicht erweiterbar
                    case 0: { // suche nach rechts weiter
                        if(checkFind(x, y, 1, 0, searchString)) { // überprüfe den fund, ned das es nur zufällig der buchstabe war und der rest nich passt
                            printf("String '%s' an Position %d|%d in Richtung %d|%d gefunden.\n", searchString, x, y, 1, 0);
                            printMatrix(x, y, 1, 0, strLenght(searchString));
                            return;
                        }
                        break;
                    }
                    case 1: { // suche nach rechts unten weiter
                        if(checkFind(x, y, 1, 1, searchString)) {  // überprüfe den fund, ned das es nur zufällig der buchstabe war und  der rest nich passt
                            printf("String '%s' an Position %d|%d in Richtung %d|%d gefunden.\n", searchString, x, y, 1, 1);
                            printMatrix(x, y, 1, 1, strLenght(searchString));
                            return;
                        }
                        break;
                    }
                    case 2: { // suche nach unten weiter
                        if(checkFind(x, y, 0, 1, searchString)) {  // überprüfe den fund, ned das es nur zufällig der buchstabe war und  der rest nich passt
                            printf("String '%s' an Position %d|%d in Richtung %d|%d gefunden.\n", searchString, x, y, 0, 1);
                            printMatrix(x, y, 0, 1, strLenght(searchString));
                            return;
                        }
                        break;
                    }
                    case 3: { // suche nach links unten weiter
                        if(checkFind(x, y, -1, 1, searchString)) {  // überprüfe den fund, ned das es nur zufällig der buchstabe war und  der rest nich passt
                            printf("String '%s' an Position %d|%d in Richtung %d|%d gefunden.\n", searchString, x, y, -1, 1);
                            printMatrix(x, y, -1, 1, strLenght(searchString));
                            return;
                        }
                        break;
                    }
                    case 4: { // suche nach links weiter
                        if(checkFind(x, y, -1, 0, searchString)) {  // überprüfe den fund, ned das es nur zufällig der buchstabe war und  der rest nich passt
                            printf("String '%s' an Position %d|%d in Richtung %d|%d gefunden.\n", searchString, x, y, -1, 0);
                            printMatrix(x, y, -1, 0, strLenght(searchString));
                            return;
                        }
                        break;
                    }
                    case 5: { // suche nach links oben weiter
                        if(checkFind(x, y, -1, -1, searchString)) {  // überprüfe den fund, ned das es nur zufällig der buchstabe war und  der rest nich passt
                            printf("String '%s' an Position %d|%d in Richtung %d|%d gefunden.\n", searchString, x, y, -1, -1);
                            printMatrix(x, y, -1, -1, strLenght(searchString));
                            return;
                        }
                        break;
                    }
                    case 6: { // suche nach oben weiter
                        if(checkFind(x, y, 0, -1, searchString)) {  // überprüfe den fund, ned das es nur zufällig der buchstabe war und  der rest nich passt
                            printf("String '%s' an Position %d|%d in Richtung %d|%d gefunden.\n", searchString, x, y, 0, -1);
                            printMatrix(x, y, 0, -1, strLenght(searchString));
                            return;
                        }
                        break;
                    }
                    case 7: { // suche nach rechts oben weiter
                        if(checkFind(x, y, 1, -1, searchString)) {  // überprüfe den fund, ned das es nur zufällig der buchstabe war und  der rest nich passt
                            printf("String '%s' an Position %d|%d in Richtung %d|%d gefunden.\n", searchString, x, y, 1, -1);
                            printMatrix(x, y, 1, -1, strLenght(searchString));
                            return;
                        }
                        break;
                    }
                    }
                }
            }
        }
    }
}

int _tmain(int argc, _TCHAR* argv[]) {
    bool end = false;
    int i = 0;
    char string[12];

    printf("Matrix-Suche - Waehle Aktion:\n");
    printf("1 .. Wortsuche\n");
    printf("9 .. Matrix ausgeben\n");
    printf("0 .. Program beenden\n");

    while(!end) {
        printf("\nKommando: ");
        scanf("%d", &i);
        if (i==0) {
            end = true;
        } else if (i==9) {
            printMatrix(0,0,0,0,0);
        } else if (i==1) {
            printf("Welches Wort wird gesucht? ");
            scanf("%s", &string);
            searchMatrix(string);
        }
    }
    return 0;
}
```

im großen und ganzen also das, was ich schon prototypisch entwickelt hatte hier. die printMatrix funktion is ebbes aufgeplustert, da ich die für ne anzeige des gefundenen strings mitbenutz - klappt soweit ganz gut. mit "kein fund" hab ichs jetz garnich probiert *hm* na wird scho passen ^^

ABER: mir fielen noch 2 elementare dinge auf, wo ich mich frag, wieo das bei dir überhaupt funzt 
zum einen: matrix is vom typ int. auch wenn du die mit chars initialisierst, da stehen int werte drin. ham wir ja schon gelernt - char in int gecasted ergibt den ascii wert des zeichens. soweit kein problem. bei printf("%c", matrix[x][y]); macht das auch nix aus, das hier nen char verlangt wird und nen int geliefert und die funktion das wohl dann intern casted (solange möglich, in unserem fall hier isses das). aber, wir vergleichen ja auch häufiger buchstaben/chars des suchwortes mit dem wert der matrix an ner x|y position. sprich, du vergleichst nen char mit nem int value. kA ob er das auch automatisch dann macht, aber ich hab fürn notfall nen (char)matrix[x][y] draus gemacht. das es bei dir funzt, spricht für ne automatische umwandlung.

gut, und dann hab ich noch nen logischen fehler enddeckt: deine matrix-variable is falsch aufgebaut. sie sieht zwar optisch richtig aus, ist aber "intern" über die diagonale gespiegelt. ich hatte die nämlich mal ausgeben lassen, und da war security plötlich von oben nach unten geschrieben in der ersten spalte >< das mag vom programm her kein eigentliches problem sein, aber fürs eigene verständnis finde ich, is das nen böser stolperstein. wenn man die matrix im code liest, würde ich persönlich davon ausgehen, dass das S von Security an position 0|1 steht - es steht aber in wirklichkeit an 1|0. das verwirrt ^^ deshalb findest du bei mir bei der matrix deklaration ne angepasste variante.

zur erklärung: du hast ja matrix[x=2][y=2] = { {a, b}, {c, d} }; <- {a, b} steht für das x0 und {c, d} für x1. wenn mans also tabellarisch aufschreibt, ist jeder teilpart, den du hier in einer zeile aufschreibst (weils anders nich sehr schön geht ^^), eine spalte. a oder c wären dann jeweils y0 - also die erste zeile, obwohl sie im code spaltenförmig angeordnet sind. hoffe, du verstehst was ich meine.

jedenfalls: diese verdrehung kann natürlich im endeffekt zu "unerwarteten" ergebnissen/koordinaten führen. wenn man das weiss, lässt sich der ein oder andere fehler vllt vermeiden. und: bei der printMatrix funktion siehst du dann auch wunderbar, wieso man am besten zuerst die spalten in ner for-schleife durchgeht und dann erst die zeilen. du hast es dort wieder "falschherum" gemacht und dadurch wird die "intern falsche" tabelle wieder richtig gedreht. quasi falsch und falsch = richtig ^^ naja, wie ich sagte: an und für sich mags egal sein, sieht halt nur blöde aus, wenn er sagt "fund bei 1|0" und in der ausgabe steht das teil aber bei 0|1 >< man muss hier also schon auf ne passende harmonie achten.

nun gut, vllt hilft dir mein laufendes proggi ja irgendwie weiter. ich verkrümel mich erstma schnellsten ins nest...


----------



## boss3D (11. November 2012)

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

^^ Also von einer angeblichen Verdrehung der Matrix merkt man bei meiner Version gar nichts. Es stimmen auch alle Koordinaten, ohne, dass ich da jetzt manuell was hätte vertauschen müssen. Ganz habe ich auch noch nicht verstanden, was du überhaupt meinst. Werde mir deine Erklärung morgen im ausgeschlafenen Zustand noch einmal durchdenken ... 

Die einzige falsche Koordinate ist der Startwert (Spaltenkoordinate bzw. nach deiner Logik wahrscheinlich Zeilenkoordinate, was aber keine Rolle spielt, da ich eh nur mit einem Feld arbeite und keiner Matrix) von MALWARE. Die ist bei jedem Programmdurchlauf ein anderer Wert, der aber immer 7-stellig ist. Jetzt gerade z.B. 1440093. Das sieht für mich nicht nach einer Verdrehung von irgendwas aus, sondern eher, als würde ich bei diesem Wort irgendwie über die Feldgrenze hinauskommen, oder mit einem falschen Datentyp arbeiten. 
Ersteres sollte aber eigentlich nicht möglich sein, weil ich ja extra auf '\0' überprüfe. Letzteres kann's aber auch nicht wirklich sein, weil der selbe Code ja für sämtlichen anderen Wörter das richtige Ergebnis liefert. Ich hätte gehofft, du erkennst in meinen knapp 20 Zeilen der Funktion checkPosition(), wo der Hund begraben liegt (der Fehler muss ja in der Funktion sein, oder?) ...

Über die Tatsache, dass ich eine int matrix definiert habe, sonst aber eigentlich nur mit char variablen und strings arbeite und das Ganze trotzdem funktioniert, habe ich mich auch schon gewundert (). Ich habe testweise sogar schon das int vor matrix mal durch char ersetzt, hat aber überhaupt keinen Unterschied gemacht. Man kann also, denke ich, wirklich davon ausgehen, dass sich der Compiler um die nötigen Typumwandlungen kümmert.

*Ich hoffe, wir finden den kleinen Fehler bei MALWARE noch.* Wenn nicht, muss ich mich halt mit meiner jetzigen Version zufriedengeben. Ich finde die eigentlich ziemlich gut und sie liefert zu 87,5 % das richtige Ergebnis, LOL. Man darf halt nur nicht zufällig das Wort MALWARE erwischen. 

_PS: Was ich auch noch probieren möchte, ist, die Bibliotheksfunktion strstr durch selbstgeschriebenen Code zu ersetzen. Wie ich dir schon in's Profil schrieb, vermute ich stark, dass ich den Code dafür eh schon in checkPosition() drinnen stehen habe. Müsste, wenn ich richtig liege, nur etwas angepasst werden._


----------



## DarkMo (12. November 2012)

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

joa, im endeffekt is strstr genau das, was wir hier selber bauen. ursprünglich auf die ganze matrix (string in matrix) bezogen, in deinem falle jetzt auch auf string in string - also genau das selbe ^^ nur das die funktion halt nicht die position zurück gibt, sondern halt nen zeiger auf den wortanfang von dem gesuchten string im gesamtstring.

und ich meinte jau auch, das die "verdrehung" der matrix im grunde kein problem is - solange man dran denkt. bei deiner printMatrix funke haste unbewusst dran gedacht, da du hier die forschleifen genau falschherum verschachtelt hast ^^ (-> for(i) { for(j) { matrix_[j] }} statt for(j) { for(i) { matrix[j] }}). dadurch geht er die erste spalte von oben nach unten durch und schreibt sie von links nach rechts auf um dann mit der nächsten spalte weiterzumachen. aber normalerweise will man sowas ja wie den text in einem buch aufschreiben: zeile für zeile von links nach rechts. und würdest du dass so machen, dann wäre die ganze ausgabe verdreht (aber würde die interne matrix korrekt darstellen).

und warum is das so "verdreht"? ich versuchs mal zu erklären:
wenn du nen einfaches array definierst, also zum bsp int matrix[2], dann sieht dass ja so aus:


		Code:
	

int matrix[2] = {0,
                 1}

machst du daraus jetzt nen 2dimensionales array, hat man statt 0 und 1 wieder nen array. also quasi jeder array eintrag ist selber ein array:


		Code:
	

int matrix[2][2] = { {0, 1},
                     {2, 3}}

da man jetzt eben bei [][] irgendwie immer [x][y] assoziiert und x in nem koorinatensystem immer von links nach rechts geht und y von oben nach unten (oder andersrum, jedenfalls diese richtung da ^^), würde man jetzt also alle x einträge von links nach rechts aufreihen und die y teile untereinander. dann folgt sowas daraus:


		Code:
	

+-------------+
| +---+ +---+ |
| | 0 | | 2 | |
| | 1 | | 3 | |
| +---+ +---+ |
+-------------+

sprich: aus der aufgeschriebenen reihenfolge
01
23

wird plötzlich intern
02
13

^^ wie gesagt, solange man dran denkt und damit rechnet/kalkuliert, is das ja kein problem - aber mir macht sowas dann immer unnötige schierigkeiten >< daher sollte das eher als hinweis dienen. weil wenn ich dann die position der 2 ausgegeben haben will, rechne ich halt damit, das der mir jetz ne 1|0 ausschmeisst und würde mich dann wundern, wieso er aber stattdessen die 0|1 ausgibt.

und zu deiner funktion nochmal: wie gesagt, schreib die erstmal sinnvoll um. ich frag mich ja echt, wieso da überhaupt was gescheites bei rauskommt ^^ die grundlogik der funktion haut vorn und hinten nicht hin (was wohl auch das mit maleware verursachen wird).

die logik deiner schleifen da is folgende:
gehe alle buchstaben durch und vergleiche sie bis das stringende erreicht wurde.
hierbei machst du WIEDER den fehler, dass du beide strings "weiterschiebst". also den betrachteten buchstaben. du willst doch erstmal im einen string den anfangsbuchstaben des anderen strings wiederfinden. dazu musst du vom ersten string alle buchstaben nacheinander IMMER mit dem ersten des 2. strings vergleichen. sprich: hier den 2. string auch weiter zu schieben sabotiert die ganze idee dahinter.
dann gehts weiter:
wenn der aktuell betrachtete buchstabe nicht mit dem (eigentlich) anfangsbuchstaben des 2. strings übereinstimmt (auch hier vergleichst du wieder den 2. 3. 4. buchstaben des gesamtstrings mit dem 2. 3. 4. buchstaben des suchstrings - kann doch nix werden), erhöhe den zähler (für die position, wos losgeht. der gedanke ist auch wieder richtig - die ausführung sinnfrei 
und jetzt kommt ja DER knackpunkt noch in der ganzen logik:
wenn er den wortanfang von str2 in str1 NICHT gefunden hat, schaue nach dem rest von str2? das gehört in den else teil des letzten vergleichs - nämlich WENN der anfangsbuchstabe im str1 gefunden wurde, DANN musst du schauen, ob nachfolgend das ganze wort noch dranhängt. also: bau erstmal deine ganze konstruktion da um, so kann das nie was werden ^^_


----------



## Freddycbv (12. November 2012)

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

Mich hat das Problem auch interessiert, und hab auch mal ne Funktion dazu geschrieben.
Ich wollte dieses switch(){case...} der 8 Suchrichtungen vermeiden, und hab mir überlegt, dass man ja nur wissen muss, ob X, bzw. Y erhöht oder erniedrigt wird (oder gleichbleibt). Dabei ist das herausgekommen:

```
bool findExpression(char * * Matrix, int Size, char * Expression, MatrixPosition * ExprPosition) //besser Referenz, falls C++ (In ExprPosition wird die gefundene Position gespeichert)
{
    //Alle Felder der Matrix werden durchgegangen, und werden nach dem Anfangsbuchstaben durchsucht. Danach kanns in 8 Richtungen weitergehen
    for(int i = 0; i < Size; i++)
    {
        for(int j = 0; j < Size; j++)
        {
            //Für jedes Feld wird in 8 Richtungen weitergesucht
            for(int SearchMode = 0; SearchMode < 8; SearchMode++)
            {
                int XDirection = 0, YDirection = 0; //Richtung in die nach dem ersten Buchstaben weitergesucht wird -- -1 , 0 , 1 
                int X = i, Y = j; // Startposition, an der jetzt nach dem ersten Buchstaben gesucht wird
                int CurrentExprPos = 0; // Position innerhalb des gesuchten Wortes
                
                //Festlegung der Suchrichtung. 
                if((SearchMode+1)%8 >= 0 && (SearchMode+1)%8 <3) YDirection = 1; 
                else if(SearchMode > 2 && SearchMode < 6) YDirection = -1;
                if(SearchMode > 0 && SearchMode < 4) XDirection = 1;
                else if(SearchMode > 4 && SearchMode <= 7) XDirection = -1;

                if(strlen(Expression) <= 1) return false; // Expression zu klein? gleich beenden, weils keinen Sinn macht
                
                //Hier wird jetzt geprüft: Eine Schleife, die bei (i|j) beginnt, und dann in die Festgelegte Richtung weitersucht.
                //Solange alle Buchstaben übereinstimmen, wird in die festgelegte Richtung weitergegangen
                while(Expression[CurrentExprPos] == Matrix[X][Y])
                {
                    CurrentExprPos++;

                    if(CurrentExprPos == strlen(Expression)) //Wort vollständig gefunden, Ergebnis festhalten
                    {
                        //Endposition ist die jetzige Position
                        ExprPosition->EndX=X;
                        ExprPosition->EndY=Y;

                        //Startposition war das Feld an dem wir den ersten Buchstaben gefunden haben
                        ExprPosition->StartX=i;
                        ExprPosition->StartY=j;
                        return true;
                    }
                    else
                    {
                        //Und zum nächsten Buchtaben...
                        X+=XDirection; 
                        Y+=YDirection;

                        if(X<0 || Y < 0 || X >=Size || Y>=Size) break; //Um nicht aus dem Rahmen zu gehen ;)
                    }
                }
            }
        }
    }
    return false;
}
```
Ich bin bei dem Problem mit der "MALWARE" auch nicht mehr mitgekommen, da auch niemand wirklich versteht, warums da hapert, würde ich eventuell empfehlen, das ganze nochmal von vorne anzufangen, weil irgendwie ist da der Wurm drinnen.
Weil das wird nicht nur bei "MALWARE" so sein, wenn andere Matrizen getestet werden, liefert das jetzige ja keine zuverlässigen Werte, dh. in einem komplexeren Programm wären die Folgen net so schön 
Vom Prinzip her ist die Sache ja einfach, man muss an jedem Feld der Matrix nach dem Anfangsbuchstaben suchen, und dann in 8 Richtungen weiterüberprüfen. Das Startfeld ist dann das Feld, wo man den Anfangsbuchstaben gefunden hat, und das Endfeld, das letzte Feld, an dem man gemerkt hat, dass man den String gefunden hat


----------



## boss3D (12. November 2012)

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

^^ OK, danke euch beiden. War eh selber schon kurz davor, die Funktion _checkPosition()_ neu zu schreiben. Ich bin mir schon ziemlich sicher, dass meine Logik bzw. Idee gut ist, allerdings kann's schon sein, dass der Code nicht ganz das macht, was ich meine. Sooo falsch kann er aber auch wieder nicht sein, wenn er für fast alles das richtige Ergebnis liefert. Naja, mach's trotzdem neu ...

@ DarkMo
Erklären könnte ich es selber nicht, aber ich glaube, ich seh's schon was du mit "verdreht" meinst. Wenn ich's aber unbewusst eh richtig mache, will ich mir da nicht weiter den Kopf darüber zerbrechen. Ich finde das nämlich schon relativ verwirrend.


----------



## boss3D (12. November 2012)

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

Bevor ich mit der Matrix-Suche weitermachen kann, muss ich schnell ein anderes Programm machen. Dabei soll über die Leibniz-Reihe PI angenähert werden. In mehreren Runden unterschiedlich genau. 

*[EDIT]*
Hat sich schon alles erledigt. Hab's geschafft ... 

```
#include <stdio.h>

#define LIMIT_ONE 10
#define LIMIT_TWO 100
#define LIMIT_THREE 100000

double approx(double k) {
    int i=0;
    double j=0.0, result=0.0, countPos=0.0, countNeg=0.0; 

    for (i=1, j=1; i<=k; i++, j+=2) { 
        if (i%2==0) { 
            countNeg-=(1/j);
        } else {
            countPos+=(1/j);
        }
    }

    [COLOR=seagreen]/* 
    PI = (1/1 - 1/3 + 1/5 - 1/7 + 1/9 - 1/11 + 1/13 - ...) * 4

   [COLOR=seagreen] Funktionsweise: Brüche erhalten "gedankliche Indexe". Z.B. 1/1 = erster Bruch = "Index" 1. 
    Ist der Index eine gerade Zahl, berechne den Bruch und subtrahiere das Ergebnis von countNeg.
    Ist der Index eine ungerade Zahl, berechne den Bruch und addiere das Ergebnis zu countPos. 
    Das Gesamtergebnis ist countPos + countNeg und das Ganze * 4.

   [COLOR=seagreen] In der Schleife zählt i die Brüche bis zur maximal gewünschten Anzahl und j die Schrittweite zwischen den Divisoren durch.
    */
    result=countPos+countNeg;

    return (result*4);
}

int main(void) {
    int k=0;

    printf("Bruchanzahl Naeherungswert\n==============================\n");
    for (k=1; k<=LIMIT_ONE; k++) { [COLOR=seagreen]/* k ist immer Anzahl der Brüche, für die die Berechnung stattfinden soll */        if (k==LIMIT_ONE) {
            printf("%d %26.15lf\n", k, approx((double)k));
        } else {
            printf("%d %27.15lf\n", k, approx((double)k));
        }
    }
    for (k=20; k<=LIMIT_TWO; k+=10) {
        if (k==LIMIT_TWO) {
            printf("%d %25.15lf\n", k, approx((double)k));
        } else {
            printf("%d %26.15lf\n", k, approx((double)k));
        }
    }
    for (k=1000; k<=LIMIT_THREE; k*=10) {
        if (k==(LIMIT_THREE/10)) {
            printf("%d %23.15lf\n", k, approx((double)k));
        } else if (k==(LIMIT_THREE)/100) {
            printf("%d %24.15lf\n", k, approx((double)k));
        } else {
            printf("%d %22.15lf\n", k, approx((double)k)); 
        }
    }
    putchar('\n');

    return 0;
}
```
Weiter geht's mit der Matrix. Aber erst schlafen gehen (siehe Uhrzeit des edits) ...


----------



## boss3D (13. November 2012)

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

_@ Mods
Sorry für Tripple-Posting, aber ich editiere eh schon, was das Zeug hält. Wenn ich jede News in's letzte Posting reineditiere, haben wir ein Posting mit ~ 10 Edits und kein Mensch sieht, dass sich im Thread was getan hat._

Habe die Funktion jetzt neu geschrieben und jetzt geht's!!! Funktioniert absolut richtig für alles ...  

```
int checkPosition(char *string1, char *string2) {
    int i=0, j=0, length=checkLength(string2), count=0, start=0;

    while (*(string1+i)!='\0' || *(string2+i)!='\0') {
        start=i;
        if (*(string1+i) == *(string2+j)) {
            j++;
            if (j==length) {
                return (start-(length-1));
            }
        }
        i++;
    }
}
```
Habe zusätzlich auch schon eine Funktion geschrieben, die mir die Bibliotheksfunktion strstr ersetzt und die funktioniert ebenfalls einwandfrei! 

```
int compareStrings(char *string1, char *string2) {
    int i=0, j=0, length=checkLength(string2);

    while (*(string1+i)!='\0' || *(string2+i)!='\0') {
        if (*(string1+i) == *(string2+j)) {
            j++;
            if (j==length) {
                return 0;
            }
        }
        i++;
    }

    return 1;
}
```
Da die beiden Funktionen _checkPosition()_ und _compareStrings()_ extrem ähnlich sind, will ich es jetzt nur noch schaffen, sie zu einer Funktion zu kombinieren. Dann hätten wir alles geschafft. 

*[EDIT]*
Soeben die Kombination der Funktionen auch noch geschafft! _checkPosition()_ ist Geschichte. Hier der finale Code:


Spoiler





```
#include <stdio.h>
#include <stdlib.h>

#define ROWS 12
#define COLUMNS 12

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

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

    return length;
}

[B][COLOR=royalblue]int compareStrings(char *string1, char *string2) {
    int i=0, j=0, length=checkLength(string2), count=0, start=1;
 [COLOR=royalblue]     while (*(string1+i)!='\0' || *(string2+i)!='\0') {
        start=i;
        if (*(string1+i) == *(string2+j)) {
            j++;
            if (j==length) {
                return (start+1-(length-1));
            }
        }
        i++;
    }
 [COLOR=royalblue]     return 0;
}[/B]

void searchMatrix(char *string, int matrix[ROWS][COLUMNS]) {
    int i=0, j=0, k=0, l=0, length=checkLength(string);
    char searchString[13];

    while (i<ROWS) {
        for (j=0; j<COLUMNS; j++) {
            searchString[j]=matrix[i][j]; 
        }
        [B][COLOR=royalblue]if (compareStrings(searchString, string)) {[/B] [COLOR=seagreen]/* wenn Rückgabewert von [I]compareStrings()[/I] ungleich 0 */            printf("%s found horizontally! %d %d\n", string, i+1, [B][COLOR=royalblue]compareStrings(searchString, string)[/B]);
            break;
        } else {
            i++;
            if (i==12) {
                while (k<COLUMNS) {
                    for (l=0; l<ROWS; l++) {
                        searchString[l]=matrix[l][k];
                    }
                    [COLOR=royalblue][B]if (compareStrings(searchString, string)) {[/B]                        printf("%s found vertically! %d %d\n", string, [COLOR=royalblue][B]compareStrings(searchString, string)[/B], k+1);
                        break;
                    } else {
                        k++;
                        if (k==12) {
                            printf("%s not found!\n", string);
                            break;
                        }
                    }
                }
            }
        }
    }
}

void printMatrix(int matrix[ROWS][COLUMNS]) {
    int i=0, j=0;

    printf("\n+---+---+---+---+---+---+---+---+---+---+---+---+\n");
    for (i=0; i<ROWS; i++) {
        for (j=0; j<COLUMNS; j++) {
            printf("| %c ", matrix[i][j]);
            if (j==11) {
                printf("|\n+---+---+---+---+---+---+---+---+---+---+---+---+\n");
            }
        }
    }
}

int main(void) {
    int matrix[ROWS][COLUMNS] = {{'X', 'S', 'E', 'C', 'U', 'R', 'I', 'T', 'Y', 'C', 'O', 'T'},
                                 {'M', 'E', 'D', 'I', 'A', 'H', 'E', 'R', 'C', 'S', 'T', 'A'},
                                 {'K', 'C', 'F', 'X', 'J', 'A', 'E', 'S', 'I', 'I', 'L', 'S'},
                                 {'M', 'U', 'I', 'N', 'T', 'R', 'U', 'S', 'I', 'O', 'N', 'K'},
                                 {'A', 'R', 'R', 'Z', 'F', 'W', 'N', 'K', 'I', 'G', 'V', 'Z'},
                                 {'L', 'E', 'E', 'N', 'C', 'R', 'Y', 'P', 'T', 'I', 'O', 'N'},
                                 {'W', 'K', 'W', 'O', 'R', 'M', 'P', 'E', 'U', 'O', 'J', 'X'},
                                 {'A', 'V', 'A', 'M', 'D', 'N', 'D', 'P', 'J', 'H', 'A', 'L'},
                                 {'R', 'L', 'L', 'N', 'V', 'I', 'R', 'U', 'S', 'P', 'E', 'E'},
                                 {'E', 'W', 'L', 'D', 'D', 'E', 'X', 'O', 'L', 'T', 'P', 'U'},
                                 {'X', 'J', 'P', 'R', 'C', 'T', 'C', 'P', 'A', 'P', 'R', 'C'},
                                 {'G', 'K', 'B', 'U', 'F', 'F', 'E', 'R', 'S', 'L', 'T', 'B'}};
    int i=0;
    char string[13];

    printf("Matrix Search - Available commands:\n");
    printf("1 .. Enter a search string\n");
    printf("9 .. Print the matrix\n");
    printf("0 .. Quit the program\n");
    
    for ( ; ; ) { 
        printf("\nPlease enter your command: ");
        scanf("%d", &i);
        if (i==0) {
            exit(0);
        } else if (i==9) {
            printMatrix(matrix);
        } else if (i==1) {
            printf("Please enter search string: ");
            scanf("%s", &string);
            searchMatrix(string, matrix);
        }
    }

    return 0;
}
```



Danke für die super Hilfe!!!


----------



## boss3D (15. November 2012)

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

Das Palindrom-Beispiel hatten wir schon mal, allerdings habe ich jetzt einen ganz neuen Lösungsansatz (der auch bereits einwandfrei funktioniert, wenn ich jedes Wort in ein eigenes char array stecke). Doof nur, dass ich nur dann überhaupt eine Ausgabe bekomme, wenn ich diese wie im auskommentierten Teil in der main mache. Wenn sie so umgesetzt wird, wie im Code blau markiert, bekomme ich eine Windows Fehlermeldung. Dabei hat exakt diese Ausgabe bei der anderen Version des Programms super funktioniert ... Why?

```
#include <stdio.h>

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

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

    return length;
}

int checkPalindrome(char *s) {
    int i=0, j=0, length=checkLength(s);
    char firstHalf[50]={0}, secondHalf[50]={0}; 
    
    [COLOR=seagreen]/* Wandle alle Großbuchstaben in Kleinbuchstaben um. */    for (i=0; i<length; i++) {
        if (*(s+i) >= 'A' && *(s+i) <= 'Z') {
            *(s+i)+=32;
        }
    }

    [COLOR=seagreen]/* 
    Zerlege das zu überprüfende Wort in 2 Hälften und speichere jede in einem eigenen string.
    Der string, der die zweite Worthälfte bekommt, muss verkehrt herum angefüllt werden. 
    */    for (i=0, j=(length-1); i<((length-1)/2), j>((length-1)/2); i++, j--) {
        *(firstHalf+i)=*(s+i);
        *(secondHalf+i)=*(s+j);
    }

    [COLOR=seagreen]/* Vergleiche die beiden Strings. */    i=0;
    while (*(firstHalf+i) != '\0' || *(secondHalf+i) != '\0') {
        if (*(firstHalf+i) != *(secondHalf+i)) {
            return 1;
        }
        i++;
    }

    return 0;
}

int main(void) {
    int i=0;
   [COLOR=royalblue][B] char *s[] = {"Hannah", "Smartphone", "Retsinakanister", "Lagerregal", "programmieren", 0 };

    while (*(s+i) != '\0') {
        if (checkPalindrome(*(s+i))==0) {
            printf("%s is a Palindrome!\n", *(s+i));
        } else {
            printf("Sorry, %s isn't a Palindrome.\n"[/B][COLOR=royalblue][B][COLOR=royalblue][B], *(s+i)[/B]);
        }
        i++;
    }[/B]
  [COLOR=seagreen]  /*
    [COLOR=seagreen][COLOR=royalblue][COLOR=seagreen]char *s1 = "Hannah", *s2 = "Smartphone", *s3 =  "Retsinakanister", *s4 = "Lagerregal", *s5 = "programmieren";    

    if (checkPalindrome(s1)==0) {
        printf("%s is a Palindrom!\n", s1);
    } else {
        printf("%s isn't a Palindrom.\n", s1);
    }
    if (checkPalindrome(s2)==0) {
        printf("%s is a Palindrom!\n", s2);
    } else {
        printf("%s isn't a Palindrom.\n", s2);
    }
    if (checkPalindrome(s3)==0) {
        printf("%s is a Palindrom!\n", s3);
    } else {
        printf("%s isn't a Palindrom.\n", s3);
    }
    if (checkPalindrome(s4)==0) {
        printf("%s is a Palindrom!\n", s4);
    } else {
        printf("%s isn't a Palindrom.\n", s4);
    }
    if (checkPalindrome(s5)==0) {
        printf("%s is a Palindrom!\n", s5);
    } else {
        printf("%s isn't a Palindrom.\n", s5);
    }
    putchar('\n');
    */
    return 0;
}
```


----------



## Freddycbv (16. November 2012)

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

mhh, verstehe ich auch nicht, bei mir funktionieren sogar beide deiner "main's" nicht.
Viual Studio meckert was von einem verletzten kritischen Bereich, also hab ich mal probiert, wie's funktionieren könnte, und das kam raus:

```
int checkPalindrome(char *[COLOR=blue]S) {
[COLOR=blue]    char s[50];
    strcpy(s,S); //kopiert den Array S in s    int i=0, j=0, length=checkLength(s);     char firstHalf[50]={0}, secondHalf[50]={0};
    
    [COLOR=seagreen]/* Wandle alle Großbuchstaben in Kleinbuchstaben um. */
    //...    }
```
So läuft das Programm bei mir durch, und erkennt die Palindrome . Warum man nicht den an die Funktion übergebenen String benutzen darf/kann, ist mir suspekt. Muss etwas mit dem Array von char Arrays zu tun haben. Denn ob man (wie oben) den 2.String in checkPalindrome(), oder schon in der main() ist egal:

```
checkPalindrome() jetzt wieder normal, aber "Umwandlung" schon in der main()
int checkPalindrome(char *[COLOR=blue]s) {
[COLOR=blue]     int i=0, j=0, length=checkLength(s);     char firstHalf[50]={0}, secondHalf[50]={0};    
    [COLOR=seagreen]/* Wandle alle Großbuchstaben in Kleinbuchstaben um. */
    //...}
int main(void) {
    int i=0;
    
    char *s[] = {"Hannah", "Hanah", "Retsinakanister", "Lagerregal", "programmieren", 0 };

    while (*(s+i) != '\0') {
[COLOR=blue]        char str[100];
        strcpy(str,*(s+i));        if (checkPalindrome([COLOR=blue]str)==0) {
            printf("%s is a Palindrome!\n", *(s+i));
        } else {
            printf("Sorry, %s isn't a Palindrome.\n", *(s+i));
        }
        i++;
    }
}
```
Zur Bestimmung der Länge, und zur Umwandlung in Klein, bzw. Großbuchstaben, gibts in C schon ein paar Standardfunktionen:
Die Länge eines Strings gibt strlen(s) zurück, char in Kleinbuchstaben geht mit c = tolower(c), und in Großbuchstaben mit c = toupper(c)
Allerdings immer nur einen einzelen char, man muss sich also eine Schleife für ein Array basteln:

```
for (i=0; i<length; i++) {
    *(s+i) = tolower(*(s+i)) //Würde s[i] anstatt *(s+i) nicht übersichtlicher aussehen :) ?
}
```



Spoiler



noch schneller gehts so:

```
int checkPalindrome2(char * S)
    {
    //Bestimmung der Länge
    const int length = strlen(S);
    //Notwendiger Zweit-String
    char s[50];
    //String2 wird String1 kleingeschrieben
    for(int i = 0; i <= length;i++)
        s[i] = tolower(S[i]);

    //nach Palindrome suchen: abbrechen, wenn vorderer Buchstabe nicht dem hinteren Buchstaben entspricht
    for(int i = 0; i < length/2; i++)
        if(s[i] != s[(length-1)-i]) return 1;
    
    //wenn nicht abgebrochen wurde, wars ein Palindrome!
    return 0;
    }
```


----------



## DarkMo (16. November 2012)

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

hehe, sowas hab ich auch letztens in LISP gesehn - war ne recht simple lösung: den basisstring umkehren und diese beiden dann vergleichen - feddich ^^


```
#include <stdio.h>

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

[COLOR=seagreen]/* Wandle alle Großbuchstaben in Kleinbuchstaben um. */char* unshift(char* s) {
     int i;
    for (i=0; i<length; i++) {
        if (*(s+i) >= 'A' && *(s+i) <= 'Z') *(s+i)+=32;
    }
    return s;
}

[COLOR=seagreen]/* String umkehren. */char* reverseString(char *s) {
    int i, j, length=checkLength(s);
    char reverse[length]; // geht das? ^^ oder muss das ne konstante sein?

    [COLOR=seagreen]/* kehre den string um */    for (i=0; i<length; i++) *(reverse+length-1-i)=*(s+i); // i<length - nich lenght-1 ^^

    return reverse;
}

int main(void) {
    int i=0;
     char *s[] = {"Hannah", "Smartphone", "Retsinakanister", "Lagerregal", "programmieren", 0 }; // müsste man am ende nich '\0' schreiben statt ner ollen 0? ^^

    while (*(s+i) != '\0') {
        if (unshift(*(s+i)) == reverse(unshift(*(s+i)))) printf("%s is a Palindrome!\n", *(s+i));
        else printf("Sorry, %s isn't a Palindrome.\n", *(s+i));
        i++;
    }
}
```
geht recht simpel und der vorteil is: man brauch sich ned wegen der "mitte" sorgen machen (gerade bei ungerade-langen strings).


----------



## boss3D (16. November 2012)

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

@ Freddycbv
Bibliotheksfunktionen sollen unbedingt vermieden werden, laut Aufgabenstellung. Dass es für fast alles was gibt, weiß ich eh. 

Muss wohl wirklich irgendwie daran liegen, dass sich _checkPalindrom()_ nicht auskennt, welches array denn nun genau übergeben wird. Werde deine Idee, jedes Wort zuerst in ein eigenes array zu speichern, gleich einmal ausprobieren. Melde mich dann, ob's bei mir auch zum Erfolg geführt hat. Wenn es wirklich daran liegt, hätte ich aber gerne noch von irgendjemandem eine Erklärung ...
Besonders in Hinblick auf die Tatsache, dass es im alten Code anstandslos funktioniert.

@ DarkMo
Jo, der Ansatz ist so simple und doch clever, dass ich gleich dachte, das muss ich ausprobieren. Ist mir übrigens beim Call of Duty 4 Zocken eingefallen.  

_PS: Du kannst nicht length (ist ja aufgrund der unterschiedlichen Wörter unterschioedlich lange bzw. "variabel") als Größenangabe nehmen. Muss, wie du dir schon gedacht hast, ein konstanter Wert sein. Deswegen habe ich auch [50] angenommen, bei den beiden neuen strings.

_*[EDIT]*
Freddycbv, du hattest recht! Das jeweils an _checkPalindrome()_ übergebene Wort muss wirklich erst lokal in einem eigenen string gespeichert werden, bevor damit gearbeitet werden kann. Habe genau so einen neuen string eingefügt und plötzlich funktioniert's absolut perfekt! Jetzt hätte ich, wie gesagt, aber gerne von irgendjemandem die Erklärung dafür ...

```
#include <stdio.h>

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

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

    return length;
}

int checkPalindrome(char *s) {
    int i=0, j=0, length=checkLength(s);
    char [COLOR=royalblue][B]checkString[50]={0}[/B], firstHalf[25]={0}, secondHalf[25]={0}; 
    
    [COLOR=seagreen]/* Speichere das jeweils übergebene Wort in checkString */    [B][COLOR=royalblue]for (i=0; i<length; i++) {
        *(checkString+i)=*(s+i);
    }[/B]
    
    [COLOR=seagreen]/* Wandle alle Großbuchstaben in Kleinbuchstaben um. */    for (i=0; i<length; i++) {
        if (*(checkString+i) >= 'A' && *(checkString+i) <= 'Z') {
            *(checkString+i)+=32;
        }
    }

    [COLOR=seagreen]/* 
    Zerlege das zu überprüfende Wort in 2 Hälften und speichere jede in einem eigenen string.
    Der string, der die zweite Worthälfte bekommt, muss verkehrt herum angefüllt werden. 
    */    for (i=0, j=(length-1); i<((length-1)/2), j>((length-1)/2); i++, j--) {
        *(firstHalf+i)=*(checkString+i);
        *(secondHalf+i)=*(checkString+j);
    }

    [COLOR=seagreen]/* Vergleiche die beiden strings. */    i=0;
    while (*(firstHalf+i) != '\0' || *(secondHalf+i) != '\0') {
        if (*(firstHalf+i) != *(secondHalf+i)) {
            return 1;
        }
        i++;
    }

    return 0;
}

int main(void) {
    int i=0;
    char *s[] = {"Hannah", "Smartphone", "Retsinakanister", "Lagerregal", "programmieren", 0 };

    while (*(s+i) != '\0') {
        if (checkPalindrome(*(s+i))==0) {
            printf("%s is a Palindrome!\n", *(s+i));
        } else {
            printf("Sorry, %s isn't a Palindrome.\n", *(s+i));
        }
        i++;
    }

    return 0;
}
```
_PS: 0 oder NULL am Ende des strings mit den Wörtern sollte stimmen. Funktioniert ja damit, wenn sonst keine Fehler im Code sind._


----------



## DarkMo (16. November 2012)

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



boss3D schrieb:


> _PS: Du kannst nicht length (ist ja aufgrund der unterschiedlichen Wörter unterschioedlich lange bzw. "variabel") als Größenangabe nehmen. Muss, wie du dir schon gedacht hast, ein konstanter Wert sein. Deswegen habe ich auch [50] angenommen, bei den beiden neuen strings._


_
stimmt, das problem hatte ich bei meinem open gl ding auch, wo ich arrays variabler länge bauen musste um die an die gpu zu senden ^^ geht ganz easy:


		Code:
	

int length = checkLength(s);
char *reverse;
reverse = new char[length];
// zugriff dann einfach mit
reverse[index] = 'C'; // oder so

ich weis nur ned, ob das c is, glaub das is c++ (un kA obs bur c sein durft).



boss3D schrieb:



PS: 0 oder NULL am Ende des strings mit den Wörtern sollte stimmen. Funktioniert ja damit, wenn sonst keine Fehler im Code sind.

Zum Vergrößern anklicken....

joa eben, NULL oder eben \0 hätt ich ohne weiteres geglaubt, aber das ne simple integer 0 geht, hätt ich nich gedacht ^^_


----------



## Dragonix (16. November 2012)

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

Variable Length - Using the GNU Compiler Collection (GCC)
Ansonsten:
C: *alloc, free
C++: new, delete

Siehe auch: Galileo Computing :: C von A bis Z – 14 Dynamische Speicherverwaltung

Ich lass hier auch gleich mal den Hinweis auf Valgrind (oder ähnliche Tools) fallen...


----------



## Freddycbv (16. November 2012)

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

Ich hab ne weitere Lösung gefunden, um das komische Array - Problem zu lösen (und habe auch eine Vermutung, worans liegen könnte )

```
int main(void) {
        int i=0;
        [COLOR=blue]char s[6][16] = {"Hannah", "Hanah", "Retsinakanister", "Lagerregal", "programmieren", 0 };
        while ([COLOR=blue]*(s+i)[0] != 0) {
            if (checkPalindrome(*(s+i))==0) {
                printf("%s is a Palindrome!\n", *(s+i));
            } else {
                printf("Sorry, %s isn't a Palindrome.\n", *(s+i));
            }
            i++;
        }
    return 0;
}
```
Ich denke, durch den Zeiger auf ein ("undefiniert großes" (was es ja eigentlich nicht ist, aber die Klammern [] sind ja leer )) Array, kommt es entweder zu Speicherproblemen (Zeiger bedeutet nicht, dass da auch unbedingt freier Speicherplatz dahinter steht!), oder er verwursctelt sich irgendwie zwischen den einzelnen Arrays. (Vielleicht gibts je einen, der hier genau weiß, was auf niedrigerer ebene abläuft, und warum dann der Computer streikt )
Naja, durch char s[6][16] weiß das Programm ganz genau, wo es dran ist, und so läufts jetzt auch ohne irgenwelche Array-Schieberreien


----------



## boss3D (16. November 2012)

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

^^ Dynamische Speicherverwaltung mit malloc, calloc und free ist mir genauso bekannt, wie Matrizen, aber beides sollte für dieses Beispiel nicht verwendet werden, weil wir zu dem Zeitpunkt, als das Hausübung war (vor ca. 1.5 Jahren) in C noch nicht bei diesen Dingen waren. Da kannten wir gerade mal Schleifen, statische Felder und Zeiger. 

Ich kenne zwar jetzt fast alles in C, aber ich will die Programme trotzdem nur mit den Dingen noch einmal machen, die ich damals zur Verfügung hatte. 

Was mich im Moment am meisten interessiert, ist, wieso das ...

```
char *s[] = {"Hannah", "Smartphone", "Retsinakanister", "Lagerregal", "programmieren", 0 };
```
... in der ersten Version des Programms einwandfrei funktioniert, OHNE, dass ein zusätzlicher Zeichen-string für das jeweilige Wort angelegt werden hätte müssen.

^^ Bis mir das wer verraten kann, will ich probieren, ein bisschen an der Effizienz unseres jetzigen Ansatzes zu arbeiten. 4 Schleifen sind wohl nicht nötig?! Vielleicht lassen sich ein paar Dinge kombinieren. Mal schauen.


----------



## Freddycbv (16. November 2012)

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

Darum :

```
/* Wandle alle Großbuchstaben in Kleinbuchstaben um. */
    for (i=0; i<length; i++) {
        if (*(s+i) >= 'A' && *(s+i) <= 'Z') {
            [COLOR=blue]*(s+i)+=32;        }
    }
```
Du veränderst den inhalt des übergebenen Arrays, dass hast du bei der 1.Version nicht gemacht. (aber bis man darauf kommt ... )
Durch die Änderung der Arrays verletzt das Programm aktiv (weil du jetzt ja schreibst, und nicht mehr liests) gegen das Speichermanagement, und das Programm stürzt ab.
Ich bin mir grad wirklich nicht sicher, aber ich vermute, dass char *s[] ={"...","...","..",...} den Speicher nicht richtig reserviert 
Ich bin echt froh, mittlerweile std::string und die Containerklassen zu benutzen, weil wenn man den Pointer-Kram nicht zu 100% richtig drauf hat, passieren einem immer wieder so doofe Fehler, von denen man garnet wirklich weiss, was man falsch gemacht hat


----------



## DarkMo (16. November 2012)

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

an und für sich kann das ja nur eine abfolge von chars "speichern". aber hier will man ne abfolge einer abfolge von chars speichern - quasi. ein char dürfte 8Bit groß sein (unicode 16) und wenn du da jetzt char *s[5] machst, sucht er sich 40Bit freien speicher und "belegt"/reserviert ihn. der zeiger zeigt nun also auf adresse 1427463 im speicher und das wäre s[0] szs. um auf dieses ominöse *(s+1) (s[1] geht bestimmt auch), zählt er nun also nochmal 4 bit druff und liest dann also ab adresse 1427463 + sizeof(char) = 1427463 + 8 = 1427471. wenn du jetzt da drin "abc" und "def" speicherst, würde er ja schon den speicherbereich sprengen. KANN aber natürlich auch sein, dass er dann 2 zeiger auf jeweils "abc" und "def" da reinspeichert. sofern der zeiger dann nich größer wie die 8bit sin, sollte es gehn. wenn du jetz allerdings diese zeigeradressen manipulierst, gehts freilich schief.

*(s+i) += 32;
gehn wir also davon aus: *s zeigt auf unsere adresse 1427463 und ist 40bit lang (also bis 1427503). nun schreiben wir "abc" an erste stelle und anstelle dieser charfolge bekommen wir wieder einen zeiger zu ihr. *s zeigt also auf die speicherzelle 1427463 an der der pointer auf speicherzelle 3946534 zeigt (da steht nun unser "abc"). "abc" geht also von 3946534 bis 394653 + (3*8) = 3946534 + 24 = 3946558.nun änderst du mit oben genannter zeile aber diesen pointer da um +32. er zeigt also quasi nun 8bit hinter unser "abc" was entweder ne speicherschutzverletzung auslöst oder eben dazu führt, dass er sagt "ausserhalb des arrays" oder sowas.


leider nur ne vermutung, vllt weis es einer genauer ><


----------



## Dragonix (16. November 2012)

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



> char *s[5] machst, sucht er sich 40Bit freien speicher und "belegt"/reserviert ihn


Nein, auf einer 32bit Platform sucht er sich 5*32Bit = 20Byte, auf einer 64bit Platform sucht er sich 5*64bit = 40Byte. Warum?
char *s[5] ist ein Feld, das fünf Zeiger auf chars speichert. Kann man sich z.B. von cdecl (oder vermutlich im Repo eurer Distribution) erklären lassen.

Der Code lässt sich also "übersetzen" in:

```
char *s[5];
s[0] = "Hannah";
...
s[5] = 0;
```
Schön illustriert ist das z.B. hier www.fbi.h-da.de/fileadmin/personal/h.weber/Material_PG1/Kapitel_08.pdf , Kapietel 8.10.
Auch passend zum Thema: Galileo Computing :: C von A bis Z – 12.9 Zeiger auf Zeiger und Stringtabellen

Aber Achtung:

```
char *s = "Blubb";
```
kann ziemlich gefährlich sein, weil "Blubb" als Konstant betrachtet wird und somit unter Umständen in Speicher steht, der als nicht veränderbar markiert ist, korrekt wäre somit:

```
const char *s = "Blubb";
```

Beispielsweise crasht folgendes

```
char *a = "Hallo";
        a[1] = 'e';
        printf("%s\n", a);
```
So merkt's dann auch der Übersetzer:

```
const char *a = "Hallo";
        a[1] = 'e';
        printf("%s\n", a);
```

Siehe auch: https://www.securecoding.cert.org/c...rs+to+const+when+referring+to+string+literals


----------



## boss3D (16. November 2012)

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

^^ Danke für die super Erklärung! Leuchtet ein. 

Indirekt hilft mir das zusätzliche Feld, in dem ich jetzt immer das zu überprüfende Wort speichere, bevor ich damit arbeite, sogar. So kann ich nämlich trotzdem in der main die ursprünglichen Wörter ausgeben lassen. Würde ich das genannte Feld ausgeben lassen, würden plötzlich nur noch Kleinbuchstaben, anstatt der originalen Wörter darstehen.

BTW: So könnte man die Funktion _checkPalindrome()_ noch ein Bisschen verkürzen. Vielleicht ginge noch mehr durch weitere Schleifenverschachtelung, aber da stellt sich dann schon wieder die Frage, ob's der Effizienz/Performance noch helfen würde, oder nur mehr dem Erscheinungsbild des Codes. 

```
int checkPalindrome(char *s) {
    int i=0, j=0, length=checkLength(s);
    char checkString[50]={0}, firstHalf[25]={0}, secondHalf[25]={0}; 
    
    [COLOR=seagreen]/*
    Speichere das jeweils übergebene Wort in checkString und wandle anschließend alle 
    Großbuchstaben in Kleinbuchstaben um. 
    */    for (i=0; i<length; i++) {
        *(checkString+i)=*(s+i);
        if (*(checkString+i) >= 'A' && *(checkString+i) <= 'Z') {
            *(checkString+i)+=32;
        }
    }

   [COLOR=seagreen] /* 
    Zerlege das zu überprüfende Wort in 2 Hälften und speichere jede in einem eigenen string.
    Der string, der die zweite Worthälfte bekommt, muss verkehrt herum angefüllt werden. 
    */    for (i=0, j=(length-1); i<((length-1)/2), j>((length-1)/2); i++, j--) {
        *(firstHalf+i)=*(checkString+i);
        *(secondHalf+i)=*(checkString+j);
    }
[COLOR=seagreen]
    /* Vergleiche die beiden strings. */    i=0;
    while (*(firstHalf+i) != '\0' || *(secondHalf+i) != '\0') {
        if (*(firstHalf+i) != *(secondHalf+i)) {
            return 1;
        }
        i++;
    }

    return 0;
}
```
@ DarkMo
Du hast ja irgendwo auf der Vorseite mal gemeint, das -1 bei length-1 könnte ich weglassen. Dann funktioniert allerdings der Code nicht mehr richtig (dann ist entweder alles Palindrom, oder nichts). Hast du dich getäuscht, oder habe ich dich falsch verstanden?

*[EDIT]*
Gerade ausprobiert: In den Abbruchbedingungen der Schleife könnte ich das -1 weglassen, beim Startwert von j allerdings nicht.

```
for (i=0, j=(length-1); i<(length/2), j>(length/2); i++, j--) {
```
^^ Kann das daran liegen, dass es für das Programm keinen Unterschied macht, ob das Wort gerade, oder ungerade ist (Anzahl der Buchstaben), weil die Schleife ja nur integer überprüft und da fällt ein möglicher Nachkommateil bei der Divison einer ungerade Zahl durch 2 sowieso weg?! Eine andere Erklärung habe ich dafür ATM nicht. Wenn das hier allerdings nur Glück und Zufall ist, lasse ich das -1 für die Logik lieber stehen ...

*[EDIT2]*
Habe was Interessantes weiter vorne im Thread ausgegraben:


bingo88 schrieb:


> 5) Length = Anzahl Elemente, Text ist in str[0]  bis str[length-1] enthalten. Wenn du mit i <= length arbeitest, liest  du noch das Nullzeichen mit ein. Bei nicht-nullterminierten Strings  schmiert dir dann das Programm mit nem Fehler ab  (Speicherschutzverletzung oder ähnliches)


Wenn das stimmt und length die Nullterminierung beinhaltet, dann muss aber schon length-1 richtig sein, v.a. da ich ja von 0 weg zähle?!


----------



## boss3D (21. November 2012)

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

Habe ein neues Beispiel, bei dem ich mir ziemlich sicher bin, dass es total easy zu programmieren ist, allerdings verstehe ich nicht so ganz, was passieren soll und warum. Auf gut Deutsch: Kann mir bitte jemand die Angabe erklären?!  




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



Ich hätte auch eine Lösung in C (nicht selbstgemacht), bei der ich aus programmiertechnischer Sicht fast alles verstehe:



Spoiler





```
#include <stdio.h>
#include <stdlib.h>

int isDigit([B][COLOR=darkorange]char s[/B]) {
    char *digits = "0123456789";
    int i=0;

    for (i=0; [B][COLOR=blue]*digits[/B];[COLOR=green] [B]digits++[/B], i++) {
        if (*digits==s) {
            return i;
        }
    }

    return -1;
}

int convert(char s[]) {
    int [COLOR=darkorchid][B]value=0[/B], minus=0, digit=0;
 
    /* Leerzeichen */
    while (*s==' ' || *s=='\t') {
        s++;
    }
 
    /* Vorzeichen */
    if (*s=='-') {
        minus=1;
        s++;
    } else if (*s=='+') {
        s++;
    }
 
    while (*s != '\0') {                
        digit = [COLOR=darkorange][B]isDigit(*s)[/B];
        if (digit==-1) { /* keine Ziffer */
            break;
        }
        value = [B][COLOR=darkorchid]value*10[/B] + digit; [COLOR=red][B]**[/B]        s++;
    }
         
    if (minus != 0) {
        return -value;
    }
         
    return value;
}

int main(void) {
    char *t1 = "012431234";
    char *t2 = "  -124";
    char *t3 = " +562";
    char *t4 = "13a";
    char *t5 = " a56 ";
    char *t6 = "     +13-56a";

    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t1, convert(t1), atoi(t1));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t2, convert(t2), atoi(t2));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t3, convert(t3), atoi(t3));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t4, convert(t4), atoi(t4));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t5, convert(t5), atoi(t5));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t6, convert(t6), atoi(t6));

    return 0;
}
```



^^ Die Teile im Code, die ich nicht verstehe, oder bei denen ich zwar eine Vermutung habe, mir aber nicht sicher bin, habe ich farblich markiert.

1. *Orange*: Soll das heißen, die Funktion isDigit, wird immer genau für die Stelle des char arrays aufgerufen, auf die der Zeiger *s gerade zeigt? Ich fände das irgendwie logischer, wenn in der Parameterdeklarationsliste von isDigit char *s stehen würde (ich weiß, dass damit das gesamt array übergeben werden würde). Dann könnte ich in isDigit den array-Inhalt mit dem dortigen array vergleichen.

2. *Blau*: Was soll denn das bitte für eine Abbruchbedingung sein? Ich habe testweise *digits!='\0' hingeschrieben, aber dann stimmt die Ausgabe des Programms nicht mehr. Auf was wird hier überprüft? Jedenfalls nicht auf die Nullterminierung.

3. *Grün*: Soll das wieder heißen, ich setze den Zeiger, der immer auf ein bestimmtes Element des arrays *digits zeigt, in jedem Schleifendurchlauf um eins weiter? Wieso dann nicht *digits++?

4. *Violett*: Wozu genau brauche ich das value*10? Value wird (abgesehen von der Initialisierung) nie irgendwo berechnet oder mit einem Wert belegt, somit müsste das doch heißen 0*10 (und damit sinnlos sein)?! Lösche ich es allerdings weg, stimmt wieder die Ausgabe nicht mehr, also für irgendwas muss es gut sein, nur wozu genau?

5. *Rotes Doppelsternchen ***: Was genau wird denn überhaupt in dieser Zeile berechnet? Da wird einfach in einer int Variable das int Ergebnis von isDigit gespeichert, oder?! Und wo genau findet jetzt eigentlich wirklich die Umwandlung von char nach int statt? In _convert()_, oder in _isDigit()_. Der Funktionsname lässt vermuten in _convert()_, ich tippe aber eher auf _isDigit()_. Habe ich recht?
-------------------

Sobald mir jemand die Angabe erklärt hat, würde ich gerne mit eurer Hilfe eine eigene Lösung für das Beispiel programmieren. Was ich bis jetzt rausfinden konnte, ist, dass es scheinbar irgendwie darum geht, die Bibliotheksfunktion atoi selbst zu programmieren. 
Was sich meinem Verständnis aber noch entzieht, ist folgendes:
- Warum genau geht "012431243" als char string durch, bzw. warum gehen auch all die andernen Zahlenkombinatione als char strings durch? Ich weiß, dass hinter jedem Buchstaben, eine Zahl steckt, ASCII sei Dank, aber im Bereich von 0 bis 5 sind ja keine Buchstaben, sondern irgendwelche Sonderzeichen oder textspezifischen Sachen?!
- Warum fällt bei "13a" das a weg? a ist doch 97 als Zahl und das könnte ich doch locker in einem int speichern?!
- Wieso wird a56 zu 0? Hier wieder: 97 und 56 müsste doch locker in int passen?
- Wieso fällt beim letzten -56a weg, wenn man doch bei -124 sieht, dass auch die negativen Zahlen in int gespeichert werden können?

^^ Ich verstehe da einfach die Logik dahinter nicht ...


----------



## bingo88 (21. November 2012)

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

1. Ja, hier wird wirklich für jedes Zeichen einzeln geprüft. Die Funktion prüft also, ob EIN Zeichen eine Zahl darstellt oder nicht.

2. Wenn ich mich recht entsinne, werden alle Werte != 0 als TRUE interpretiert (gibt es ja in C nicht als eigenen Typ). So ohne es auszuprobieren, hätte ich daher auch auf 0-Terminierung getippt. Aber du sagst ja, das war's nicht... müsste ich erst mal ausprobieren ^^

3. Hier wird der Zeiger hochgezählt, ein *digits++ würde den Wert an der aktuellen Zeigerposition hochzählen (du kämst im Array nicht vorran). Und nebenbei müsste das von Dragonix angesprochene Problem auch greifen (Verändern eines String-Literals soll wohl böse sein ^^)

4. value = value * 10 + digit -> value erhält jedesmal einen neuen Wert, der erste (nach 0) ist value = digit. Nehmen wir mal die Zahl 133:

1) value = 0 * 10 + 1; (= 1)
2) value = 1 * 10 + 3; (= 13)
3) value = 13 * 10 + 3; (= 133)

Zu deinen anderen Fragen:
Die Umwandlung Zeichen -> Zahl geschieht in isDigit. Dabei werden die ASCII Werte gar nicht verwendet, sondern der Array-Index aus der for-Schleife liefert die Zahl. Durch diese Operation unter 4. wird dann die endgültige Zahl gebildet.

Das a wird ignoriert, da es nicht im char-Array vorkommt (for bei IsDigit läuft bis zum Ende durch -> return -1 -> break in der convert while-Schleife).

Hier wird ja nichts in Int gewandelt. Das erste Zeichen ist keine Zahl, also breche ab (Aufgabenstellung).

Das -56a fällt weg, da "+13-56a" keine gültige Zahl ist. Oder hast du schon mal ne Zahl gesehen, wo mittendrin ein Minus steht?  (gut "56a" ist eigentlich auch keine gültige Zahl, aber die Aufgabenstellung lässt das zu; sind halt nur Definitionen). An sich ist die Sache ganz einfach




> Wenn das stimmt und length die Nullterminierung beinhaltet, dann muss aber schon length-1 richtig sein, v.a. da ich ja von 0 weg zähle?!


Length enthält die Anzahl der Zeichen ohne Nullterminierung. Du hast also length Zeichen, von str[0] bis str[length-1]. Was ich da meinte war, wenn du mit str[length] arbeitest, liegt du im besten Fall auf dem Null-Zeichen, im schlimmsten Fall bei einer Speicherschutzverletzung (man kann auch Strings ohne Nullterminator nutzen!)


----------



## DarkMo (21. November 2012)

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

gehn wirs mal durch:
die aufgabe verlangt im endeffekt ne funktion, die aus einem string das erste zahlenvorkommen rausfiltert. sprich: sobald der erste buchstabe auftaucht, soll abgebrochen werden.

wieso verstehst du die logik dabei nich? >< bei 13a zum bsp verwertet er die 13 und das a fällt weg. das a ist ja kein buchstabe mehr. hmm, ich glaub ich weis, was du falsch verstehst. was is denn ein char und was ist ein int? ^^ beides sind variablen typen und jeder typ hat ne andere interpretation des speicherwerts, wenn mans mal so will. char 65 ist A und int 65 ist ganz simpel die 65. bei char wird ne zahl eben als ascii code betrachtet. hmm, also wenn du dieses 13a hast, dann willst du 13 raushaben, und nicht ne summe der scii werte oder so. als char sieht das dann halt so aus: [49][51][97]. und er will aus diesem "kuddelmuddel" eben die zahl extrahiert haben.

gut, weiter...
isDigit prüft ganz simpel (wies der name sagt), ob der aktuell betrachtete char des char-arrays eine zahl ist oder nicht. wenn er das gleich fürs ganze array macht, wärs ja die hauptfunktion an sich - quasi ^^ die lösung find ich allerdings irgendwie umständlich. ein einfaches

```
bool isDigit(char s) {
    if((int)s > 47 && (int)s < 58) return true;
    return false;
}
```
hätts mMn auch getan >< naja, er wollt vllt protzen. die forschleife kenn ich so nämlich auch ned, kanns mir vllt dunkel vorstellen was er da treibt. aber wie gesagt: unnötig kompliziert *find*

gut, convert(): joa, er ignoriert erstma alle leerteichen und tabulatoren und checkt dann auf nen minuszeichen. dann muss ne zahl folgen, oder es bricht ab.





```
#include <stdio.h>
int convert(char s[]) {
    int value=0;
    bool negative = false;
 
    /* Leerzeichen */
    while (*s==' ' || *s=='\t') s++;
 
    /* Vorzeichen */
    if (*s=='-') {
        negative=true;
        s++;
    } else if (*s=='+') s++; // find ich persönlich jetz unnötig, da normalerweise keiner nen + schreibt ^^ isch wär da knallhard jong! abbruch, ABBRUCH! xD
 
    while (*s != '\0') {                
        if (!isDigit(*s)) break; // ich geh hier von meiner version der isDigit funke aus

        value = value*10 + (int)*s - 48;
        s++;
    }
         
    if (negative) return -value;
    return value;
}
```
wegen dem value: schau dir das ding doch mal genau an - die variable steht innerhalb der while schleife. gehs einfach mal im kopf durch, was da passiert:
im endeffekt lässt er alle leerzeichen bla links liegen und fängt danach mit der betrachtung an. isses ne zahl, wird weitergemacht, isses keine, abgebrochen. es können also am anfang beliebig viele leerzeichen oder tabs auftreten gefolgt von maximal einem vorzeichen und dann gehts los. er betrachtet dann den rest des strings solange, bis keine zahl mehr auftaucht (das break nach dem if-check) - oder das ende erreicht is (die while-bedingung).

value startet mit 0. das erste mal bei 13a rechnet er also value = 0(unser startwert)*10+1; => 1. jetzt ist value also 1. beim zweiten durchgang findet er die 3 - value = 1(im ersten durchgang errechnet)*10+3; => 13  nun folgt ein a - abbruch. bei " a56" skippt er das leerzeichen und findet nun ein a - abbruch. value wird mit seinem initialwert von 0 zurückgegeben. "        +13-56a" -> wieder werden die leerzeichen geskipped, das vorzeichen gelesen, die 13 rausgesucht/errechnet und dann das '-' gefunden - abbruch.

also wie gesagt: es geht NICHT darum, die ascii werte zu addieren, sondern aus nem string ne zahl zu extrahieren


----------



## boss3D (21. November 2012)

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

OK, vielen Dank euch beiden!

char assoziiere ich halt immer sofort mit Buchstaben bzw. Wörtern und wenn ich da dann "umwandeln in int" lese, ist mein erster Gedanke --> ASCII ... 
^^ Das war der Logikfehler. Wäre ja auch zuviel verlangt gewesen vom Lehrer, einfach in die Angabe zu schreiben: Filtert aus dem char string gültige Zahlen, wenn vorhanden, raus.  

@ DarkMo
Die Lsg oben stammt vom Lehrer, und ja, der Typ gibt gerne mal an mit dem, was er kann. 
Ich persönlich finde ja schon das Arbeiten mit ausschleißlich Zeigern ohne Hilfsvariable etwas verwirrend. Ich hätte es immer so gemacht: *(s+i) ... i++ und nicht einfach dann den Zeiger selbst weitersetzen s++. Ich versteh's zwar, finde es aber für die Logik umständlicher, auch wenn's kürzer ist.

Den Bereich von 48 bis 57 zu prüfen finde ich echt schlau, BTW! Auf die Idee wäre ich jetzt nicht mehr gekommen, wo ihr mir den ASCII-Bezug schon ausgeredet habt. Aber so kann man sich natürlich trotzdem auf die Tabelle beziehen. 

@ bingo88
In der for-Schleife wird doch auf die Nullterminierung geprüft, hab's eben noch einmal ausprobiert und jetzt ging's. Wahrscheinlich habe ich beim Herumprobieren unabsichtlich wo einen kleinen Fehler reingebracht und deswegen ging's zuerst nicht. 

Bei dem value habe ich mich von der Schreibweise verwirren lassen. Ich schreibe nämlich nie variable = variable +/*whatever, sondern immer += oder -= oder *= oder /=. Da hätte ich es sofort gesehen. Jetzt ist es eh total logisch, dass value in jedem Schleifendurchlauf einen anderen Ausgangswert hat.

Mir bleibt vorerst nur noch eine Frage: Ich hätte ja genauso gut z.B. a56 als int speichern können, oder? Wurden in der Angabe deswegen explizit char Felder verwendet, weil bei int sonst sofort der ASCII-Wert (hier z.B. für a) erkannt werden würde und somit alles als gültige Zahl durchgehen würde?

Werde auf jeden Fall mal probieren, das Ganze eigenständig zu programmieren. Thanks, again!


----------



## boss3D (22. November 2012)

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

So, habe mal eine eigene Version geschrieben, allerdings kommt die noch nicht mit vorangestellten Buchstaben und eingeschobenen Rechenzeichen zurecht. Alles andere passt schon.

```
#include <stdio.h>
#include <stdlib.h>

int convert(char s[]) {
    int i=0, j=0, minus=0, result=0;

    [COLOR=seagreen]/* Leerzeichen/Tabulatoren entfernen und Vorzeichen prüfen */    while (*(s+i) != '\0') {
        if (*(s+j)==' ' || *(s+j)=='\t') {
            j++;
        } else if (*(s+i)=='+') {
            break;
        } else if (*(s+i)=='-') {
            minus=1;
            break;
        }
        i++;
    }

    [COLOR=seagreen]/* Prüfen auf Gültigkeit der Zahl und Rückrechnun von Dec nach Chr */    for (j; *(s+j) != '\0'; j++) {
        if (*(s+j)>=49 && *(s+j)<=57) { [COLOR=seagreen]/* ASCII-Bereich der chars */            result=result*10+*(s+j)-48;
        }
    }

    [COLOR=seagreen]/* dem Vorzeichen entsprechende Ausgabe */    if (minus==1) {
        return -result;
    }

    return result;
}

int main(void) {
    char *t1 = "012431234";
    char *t2 = "  -124";
    char *t3 = " +562";
    char *t4 = "13a";
    char *t5 = " a56 ";
    char *t6 = "     +13-56a";

    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t1, convert(t1), atoi(t1));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t2, convert(t2), atoi(t2));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t3, convert(t3), atoi(t3));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t4, convert(t4), atoi(t4));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t5, convert(t5), atoi(t5));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t6, convert(t6), atoi(t6));

    return 0;
}
```
Ich hätte es ja noch so probiert, aber da kommt nur Blödsinn raus:

```
for (j; *(s+j) != '\0'; j++) {
        if (*(s+j)>=49 && *(s+j)<=57) { [COLOR=seagreen]/* ASCII-Bereich der chars */            result=result*10+*(s+j)-48;
    [COLOR=royalblue][B]    } else {
            result=0;
        }[/B]    }
```
Und ein weiteres Problem lässt sich auch schon absehen: Wenn der Code erstmal funktioniert, wird er genau für die 6 in der Angabe vorgegebenen char Felder funktionieren, aber nicht für alle möglichen anderen. Habe nämlich schon mal testweise ++562 eingegeben, was ja 0 als Ergebnis liefern sollte. Ausgabe aber trotzdem 562 ...

Wenn erst einmal alles funktioniert, will ich deshalb das ganze noch so umändern, dass man wirklich alles mögliche eingeben könnte und es immer das selbe liefert, wie die Bibliotheksfunktion atoi.


----------



## Freddycbv (22. November 2012)

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

Vielleicht noch nicht so ganz sauber, aber so gehts:

```
[COLOR=blue] [COLOR=navy]int startPos = j;    /* Prüfen auf Gültigkeit der Zahl und Rückrechnun von Dec nach Chr */
    for (j; *(s+j) != '\0'; j++) {
        if (*(s+j)>=[COLOR=darkred]48 && *(s+j)<=57) { /* ASCII-Bereich der chars */
            result=result*10+*(s+j)-48;
        }
[COLOR=blue]        else if([COLOR=deepskyblue]!(*(s+j) == '+' || *(s+j) == '-') || [COLOR=navy]startPos != j) {
            return result;
        }    }
```
Als erstes, rot markiert, ist es wichtig auch die '0' als Zahl zu sehen, damit im untereren Abbruchkriterium, blau markiert, nicht auch die Null als Abbruch zählt.

Das Abbruchkriterium ist ja folgendes:
- Wenn etwas mitendrin im String keine Zahl ist (Dunkelblau); (Dazu muss ich natürlich wissen, ob ich mittendrinn bin, brauche also die Startposition)
ODER
- Wenn vorne keine Zahl oder + / - steht (hellblau)

Wenn abgebrochen wird, dann gibt die Funktion ihr bisheriges Ergebnis zurück. So wird aus "32432a7" 32432

EDIT: hab was übersehen:
damit auch ein eventuelles Minus gewertet wird, darf nicht sofort das Ergebnis zurückgegeben werden, sondern nur die Schleife beendet werden:

```
[COLOR=blue] [COLOR=black]       else if(!(*(s+j) == '+' || *(s+j) == '-') || startPos != j) {
           [COLOR=blue] break;        }
```


----------



## boss3D (22. November 2012)

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

Ok, vielen Dank!

So funktioniert's jetzt:

```
int convert(char s[]) {
    int i=0, j=0, minus=0, startPos=0, result=0;

    [COLOR=seagreen]/* Leerzeichen/Tabulatoren entfernen und Vorzeichen prüfen */    while (*(s+i) != '\0') {
        if (*(s+j)==' ' || *(s+j)=='\t') {
            j++;
        } else if (*(s+i)=='-') {
            minus=1;
            break;
        }
        i++;
    }

    [COLOR=seagreen]/* Prüfen auf Gültigkeit der Zahl und Rückrechnung von Dec nach Chr */    startPos=j;
    for (j; *(s+j) != '\0'; j++) {
        if (*(s+j)>=48 && *(s+j)<=57) { /* ASCII-Bereich der chars */
            result = result*10+*(s+j)-48;
        } else if (!(*(s+j)=='+' || *(s+j)=='-') || startPos!=j) {
            return result;
        }
    }

    [COLOR=seagreen]/* dem Vorzeichen entsprechende Rückgabe */    if (minus==1) {
        return -result;
    } else {
        return result;
    }
}

int main(void) {
    char *t1 = "012431234";
    char *t2 = "  -124";
    char *t3 = " +562";
    char *t4 = "13a";
    char *t5 = " a56 ";
    char *t6 = "     +13-56a";

    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t1, convert(t1), atoi(t1));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t2, convert(t2), atoi(t2));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t3, convert(t3), atoi(t3));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t4, convert(t4), atoi(t4));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t5, convert(t5), atoi(t5));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t6, convert(t6), atoi(t6));

    return 0;
}
```
Bei deinem Edit komme ich nicht ganz mit. Ich hab's ausprobiert, aber gerade mit break setzt er ein Minus, wo keines hin soll?! Ich denke, mit einem sofortigen return result(=0) stimmt das schon.


----------



## Freddycbv (22. November 2012)

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

Naja, 'return result;' gibt ein falsches Ergebnis bei zB. ("-323c47")
Bei welcher Eingabe hat er bei break ein Minus gesetzt? Eigentlich solltes damit stimmen, aber vielleicht hab ich ja was übersehen.

Wichtig ist halt nur nicht return 0; zu machen, weil sonst zB "627einPaarZeichen33" natürlich auch 0 anstatt 627 zurückgibt


```
int convert(char s[]) {
    int i=0, j=0, minus=0, result=0;

    /* Leerzeichen/Tabulatoren entfernen und Vorzeichen prüfen */
    while (*(s+i) != '\0') {
        if (*(s+j)==' ' || *(s+j)=='\t') {
            j++;
        } else if (*(s+i)=='+') {
            break;
        } else if (*(s+i)=='-') {
            minus=1;
            break;
        }
        i++;
    }
    
    int startPos = j;
    /* Prüfen auf Gültigkeit der Zahl und Rückrechnun von Dec nach Chr */
    for (j; *(s+j) != '\0'; j++) {
        if (*(s+j)>=48 && *(s+j)<=57) { /* ASCII-Bereich der chars */
            result=result*10+*(s+j)-48;
        }
        else if(!(*(s+j) == '+' || *(s+j) == '-') || startPos != j) {
            break;
        }
    }

    /* dem Vorzeichen entsprechende Ausgabe */
    if (minus==1) {
        return -result;
    }

    return result;
}
```


----------



## DarkMo (22. November 2012)

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

man kann ja als zusatzaufgabe versuchen, ne funktion zu bauen, die auch "gleichungen" berücksichtigt ^^ also +-*/ der einfachheit halber. sprich das selbe wie bisher (vorranggehende leerzeichen usw ignorieren, bei buchstaben abbrechen - ABER: nich nur das erste + - usw beachten und beim 2. abbrechen, sondern die entstehenden werte korrekt berechnen.

als bsp:
"   043+1-a5" => 44
"+123-45*2" => 156 (lineare abarbeitung fürs erste - normal würde man das ja als 123-(45*2) rechnen, sprich 33 als ergebnis)

wenn man den hier schon angekratzten fehler und vllt sogar klammern berücksichtigen will, das wird dann glaube der experten mode  naja, als stichpunkt fällt mir zumindest erstmal rekursion ein. werd mich nachher mal prototypisch (hier im eingabefeld) dran probieren ^^


----------



## boss3D (22. November 2012)

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



Freddycbv schrieb:


> Naja, 'return result;' gibt ein falsches Ergebnis bei zB. ("-323c47")
> Bei welcher Eingabe hat er bei break ein Minus gesetzt? Eigentlich  solltes damit stimmen, aber vielleicht hab ich ja was übersehen.


Stimmt, da käme ich auf 323 (ohne Minus). Wenn ich allerdings deine Version mit dem break anstelle des returns nehme, liefert mir "+13-56a" -13 (mit Minus) ...

BTW: Wir arbeiten nicht mehr mit exakt dem selben Code (siehe meine Version im vorherigen Posting). Habe z.B. die Plus-Überprüfung gelöscht, weil die mehr oder weniger sinnlos war. Die Rückgaben von result und -result hängen jetzt auch in einem if-else gemeinsam drinnen. Ändert semantisch nichts, ist aber optisch schöner. 

@ DarkMo
Also solche "wilden" Dinge überlasse ich dann lieber mal dir. 

Wenn ich mit Freddycbv die letzten Ungereimtheiten geklärt habe, möchte ich wieder die Lauflängencodierung, die wir hier schon einmal hatten, probieren. Beim ersten Anlauf haben wir uns ja in eine Sackgasse programmiert, wo kein sinnvolles Weiterarbeiten im Rahmen der Aufgabenstellung mehr möglich war. Es muss also ein neuer Ansatz her und mir schwirrt auch schon eine erste Idee im Kopf herum. Ich muss das aber zuerst ausprobieren, bevor ich sagen kann, ob wir damit ans Ziel kommen können ...


----------



## Freddycbv (22. November 2012)

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

achsooo!
Dadurch dass du das mit dem Plus herausgenommen hast, gibts jetzt den Fehler:

```
/* Leerzeichen/Tabulatoren entfernen und Vorzeichen prüfen */
    while (*(s+i) != '\0') {
        if (*(s+j)==' ' || *(s+j)=='\t') {
            j++;
        } else if (*(s+i)=='+') {
            [COLOR=blue]break;        } else if (*(s+i)=='-') {
            minus=1;
           [COLOR=blue] break;        }
        i++;
    }
```
Dieser Teil der Funktion soll ja voranstehende Tabulatoren und Leerzeichen herausfiltern, aber auch das Vorzeichen festlegen.
Mit der Plus-Abfrage geht er alle Zeichen des Strings Zeichen für Zeichen durch, und sobald er das erste Vorzeichen findet, bricht er ab(+/-)
Lässt du das mit dem Plus weg, geht er alles durch, bis er das erste Minus findet, bzw. der String zuende ist.

Gut das du das bemerkt hast!

Weil damit ist auch mein gepostetes Schnipsel nicht ganz richtig:
Das Programm muss die ersten Zeichen durchgehen, und sobald ein Zeichen außer Leerzeichen / Tabulatoren kommt, gehts an die "Zahlensuche" weiter unten
Wenn ein Vorzeichen gefunden wurde, dann muss es gesetzt werden (beim Minus), und man muss ein Zeichen weiter gehen.

Bei der "Zahlensuche" muss jetzt auch nurnoch darauf geachtet werden, ob Zahl oder Keine Zahl.
Auf Vorzeichen, bzw. erstes Zeichen muss keine Rücksicht mehr genommen werden



```
int convert(char s[]) {
    [COLOR=navy]int i=0, Vorzeichen=1, result=0;

    [COLOR=navy]/* Leerzeichen/Tabulatoren entfernen und Vorzeichen prüfen */
    for(i; *(s+i) != '\0'; i++) {
        //Beim Vozeichenfund abbrechen, und eventuell ein Minus setzen
        if(*(s+i)=='+' || *(s+i) == '-'){
            if(*(s+i)=='-'){
                Vorzeichen = -1;
            }
            i++;
            break;
        }
        //Tabulatoren und Leerzeichen ignorieren, ansonsten abbrechen
        else if (*(s+i)!=' ' && *(s+i)!='\t') {
            break;
        }
    }
    /* Prüfen auf Gültigkeit der Zahl und Rückrechnung von Dec nach Chr */
    for (i; *(s+i) != '\0'; i++) {
        if (*(s+i)>=48 && *(s+i)<=57) { /* ASCII-Bereich der chars */
            result = result*10+*(s+i)-48;
        [COLOR=navy]} else break; //abbrechen, falls keine Zahl    }

    /* dem Vorzeichen entsprechende Rückgabe */
[COLOR=navy]    return Vorzeichen * result;}
```
War jetzt vielleicht ein wenig kompliziert, aber das Problem war ja, dass bei der Vorzeichensuche folgende Ergebnisse beachtet werden müssen:
- Vorzeichen Minus
- Vorzeichen Plus
- Kein Vorzeichen (also in unserer Welt ein Plus  )
Das war bei den vorherigen Schleifen halt nicht der Fall, denn wenn kein Vorzeichen vor der ersten Zahl gefunden wurde, aber ein Minus nach der ersten Zahl, es automatisch ein Minus wurde


----------



## DarkMo (22. November 2012)

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

wegen dem return in if schleifen und kein problem... manche compiler haben damit sehr wohl ein problem ^^ die wollen unbedingt ein return, das definitiv ausgeführt wird. sieh dir zum bsp den code hier an:

```
char sinnlos(char c) {
    if(c == 'a') return 'A';
    else if(c == 'b') return 'B';
}
```
hier ist der einwand des compilers durchaus berechtigt - weil wenn c weder 'a' noch 'b' ist, wird garnichts zurückgegeben - was falsch ist, da die funktion nicht void ist sondern ein char als rückgabewert verlangt. und auch wenn man

```
char sinnlos(char c) {
    if(c == 'a') return 'A';
    else return 'B';
}
```
schreibt (einfach else statt else-if), meckert so mancher, obwohl es hier eigentlich lauffähig wäre. die sehen dann aber nur, dass da bedingte returns sind, und das darf nicht sein. daher hab ich mir bersönlich nen simples

```
char sinnlos(char c) {
    if(c == 'a') return 'A';
    return 'B';
}
```
angewöhnt ^^ dann wird garantiert nicht gemeckert, bei genauso guter funktionalität. gut, das wollt ich aber nur am rande mal erwähnt haben als "good to know".

jetzt mal zu meinem vorhaben ^^ mein plan für die simple erweiterung wäre, dass convert einen string annimmt und das erste vorkommen eines vorzeichens oder einer zahl sucht (abbruchbedingungen wie gehabt). findet er eine zahl, wird diese wi gehabt schrittweise konvertiert, findet er ein vorzeichen, schneidet er den anfang (inklusive vorzeichen) ab und schickt den rest "sich selbst" - rekursiver aufruf.

vorüberlegung: "1--12" würde auch gehen. er findet die '1', dann das '-' und übergibt einer weiteren instanz von sich selbst '-1' (das bisher bearbeitete '1-' wird abgeschnitten). hmm, nun findet er wieder ein '-' und übergibt der 3. instanz die '12' - die zur 12 ausgewertet und an die 2. instanz zurückgegeben wird. in der 2. instanz ist der value 0 und davon wird die in der 3. instanz konvertierte 12 abgezogen -> -12. diese -12 der 2. instanz geht nun zurück an unsere erste instanz, die bisher schon die '1' konvertiert hat (value is also 1) und zieht davon die -12 ab -> 1- (-12) = 1+12 = 13. hmm, is ja doch garnich so übel ^^

gut, sollte also so kein problem sein - wir brauchen nur eine hilfsfunktion substring (und die obligatorische länge). fein...


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

char* subStr(char *s, int start, int length) {
    char *sub = (char*) malloc(length + 1);
    int i;

    if(sub == NULL) exit(1); // sollte er keinen speicher allokieren können, raus hier ^^
    for(i = 0; i < start; i++) s++; // zeiger von s weiterschieben, bis der startindex erreicht wurde
    for(i = 0; i < length; i++) { // und nun length zeichen in sub kopieren
        sub[i] = *s;
        s++;
    }
    sub[i] = '\0'; // nullterminierten string basteln

    return *sub;
}

bool isDigit(char s) {
    if((int)s > 47 && (int)s < 58) return true;
    return false;
}

int convert(char s[]) {
    int value = 0, pos = 0, length = strLen(s);

    while (*s==' ' || *s=='\t') { // leerzeichen skippen
        s++; // den zeiger weiterschieben
        pos++; // und noch den index (position) aktualisieren
    }

    // vorrangestellte vorzeichen bearbeiten
    if (*s=='-') {
        pos++; // vor der substringbildung den index erhöhen, damit das vorzeichen in der nächsten instanz nicht nochmal behandelt wird (auch abschneiden)
        value -= convert(subStr(s, pos, length - pos)); // rekursiver aufruf von convert mit dem substring als parameter
        return value; // der rest wurde in den "tieferen instanzen" alles abgearbeitet, raus hier
    } else if (*s=='+') { // mit den anderen genauso verfahren
        pos++;
        value += convert(subStr(s, pos, length - pos));
        return value;
    } else if (*s=='*') {
        pos++;
        value *= convert(subStr(s, pos, length - pos));
        return value;
    } else if (*s=='/') {
        pos++;
        int tmp = convert(subStr(s, pos, length - pos));
        if(tmp != 0) value /= tmp; // division durch 0 verhindern
        return value;
    }

    // wurde kein vorzeichen gefunden, wandle das ganze gerödel in ne zahl um
    while (*s != '\0') {
        pos++;

        // weitere vorzeichen bearbeiten
        if (*s=='-') {
            value -= convert(subStr(s, pos, length - pos)); // rekursiver aufruf von convert mit dem substring als parameter
            return value; // der rest wurde in den "tieferen instanzen" alles abgearbeitet, raus hier
        } else if (*s=='+') { // mit den anderen genauso verfahren
            value += convert(subStr(s, pos, length - pos));
            return value;
        } else if (*s=='*') {
            value *= convert(subStr(s, pos, length - pos));
            return value;
        } else if (*s=='/') {
            int tmp = convert(subStr(s, pos, length - pos));
            if(tmp != 0) value /= tmp; // division durch 0 verhindern
            return value;
        }

        if (!isDigit(*s)) break; // keine ziffer mehr? raus hier

        value = value*10 + (int)*s - 48;
        s++;
    }

    return value;
}
```

hmm, jetz wüsst ich gern, ob das so funzt ^^


----------



## boss3D (22. November 2012)

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

@ Freddycbv
Ich glaube, in deiner ersten for-Schleife kannst du dir das i++ vor dem break sparen, weil du eh schon im Schleifenkopf inkrementierst.

Ich habe jetzt bei mir das else if (*(s+i)=='+') wieder reingetan und jetzt funktioniert's mit dem break anstelle von return result. Was ich aber nicht ganz verstehe, ist, wo denn jetzt der 0er im Falle von ungültigen Zahlen herkommt. Zuerst war's logisch --> return result --> result=0. Aber jetzt?
Ich vermute mal, irgendwie aus dieser Zeile: result = result*10+*(s+j)-48; ... aber wie kommt der Compiler da hin? Er geht ja nur in's else, wenn das if nicht stimmt. Und wenn das if nicht stimmt, wird doch die Anweisung darin gar nie ausgeführt?!

^^ Hach, immer diese Logiksachen. Bis bei mir da mal das Licht aufgeht ... 

@ DarkMo
Ich verstehe, was du mir bezüglich Rückgabe von Werten sagen willst, aber ich hab's noch nie erlebt, dass sich ein Compiler beschwert hätte (glaub's dir aber, dass es passieren kann). Ok, ich programmiere aber auch nur ausschließlich mit Visual Studio unter Windows. Vielleicht ist es da zufällig egal. 

Unnötig verkomplizieren will ich das Programm jetzt ehrlich gesagt nicht mehr. Die Aufgabestellung wäre ja erfüllt. Danke für eure Hilfe! 

Was ich gerne noch geklärt hätte, bezieht sich noch auf eure Kommentare zu unserem vorigen Beispiel: Palindrom


bingo88 schrieb:


> Length enthält die Anzahl der Zeichen ohne  Nullterminierung. Du hast also length Zeichen, von str[0] bis  str[length-1]. Was ich da meinte war, wenn du mit str[length] arbeitest,  liegt du im besten Fall auf dem Null-Zeichen, im schlimmsten Fall bei  einer Speicherschutzverletzung (man kann auch Strings ohne  Nullterminator nutzen!)


Length beinhaltet also alle Zeichen exklusive der Nullterminierung und du meintest, es müsste daher mit nur length/2 anstatt von (length-1)/2 im Schleifenkopf funktionieren. Nun, tut's aber nicht (falsche Ergebnisse). Wieso, wenn doch die Nullterminierung eh nicht mehr enthalten ist?


Spoiler





```
#include <stdio.h>

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

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

    return length;
}

int checkPalindrome(char *s) {
    int i=0, j=0, length=checkLength(s);
    char checkString[50]={0}, firstHalf[25]={0}, secondHalf[25]={0}; 
    
   [COLOR=seagreen] /*
    Speichere das jeweils übergebene Wort in checkString und wandle anschließend alle 
    Großbuchstaben in Kleinbuchstaben um. 
    */    for (i=0; i<length; i++) {
        *(checkString+i)=*(s+i);
        if (*(checkString+i) >= 'A' && *(checkString+i) <= 'Z') {
            *(checkString+i)+=32;
        }
    }

    [COLOR=seagreen]/* 
    Zerlege das zu überprüfende Wort in 2 Hälften und speichere jede in einem eigenen string.
    Der string, der die zweite Worthälfte bekommt, muss verkehrt herum angefüllt werden. 
    */    [COLOR=royalblue][B]for (i=0, j=(length-1); i<((length-1)/2), j>((length-1)/2); i++, j--) {[/B]        *(firstHalf+i)=*(checkString+i);
        *(secondHalf+i)=*(checkString+j);
    }

    [COLOR=seagreen]/* Vergleiche die beiden strings. */    i=0;
    while (*(firstHalf+i) != '\0' || *(secondHalf+i) != '\0') {
        if (*(firstHalf+i) != *(secondHalf+i)) {
            return 1;
        }
        i++;
    }

    return 0;
}

int main(void) {
    int i=0;
    char *s[] = {"Hannah", "Smartphone", "Retsinakanister", "Lagerregal", "programmieren", 0 };

    while (*(s+i) != '\0') {
        if (checkPalindrome(*(s+i))==0) {
            printf("%s is a Palindrome!\n", *(s+i));
        } else {
            printf("Sorry, %s isn't a Palindrome.\n", *(s+i));
        }
        i++;
    }
    putchar('\n');

    return 0;
}
```


----------



## DarkMo (22. November 2012)

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



boss3D schrieb:


> Unnötig verkomplizieren will ich das Programm jetzt ehrlich gesagt nicht mehr. Die Aufgabestellung wäre ja erfüllt.


der spaß beim programmieren fängt für mich da an, wo man selber was bastelt ^^ hier wars halt der ehrgeiz - und rekursion kann man nie genug üben 

wegen der length geschichte: die "grundlagen" kennste aber oder? also "abcde" hat die länge 5, da der index aber bei 0 anfängt, muss man hier immer -1 rechnen:


string|a|b|c|d|e
stelle|1|2|3|4|5
index|0|1|2|3|4so quasi. willst du das letzte zeichen, darfst du eben nicht string[length] nehmen, sondern string[length-1]. stelle "length" ist index length-1.
und wegen dem palindrom: abcba zum bsp ist ein palindrom - aber 5 ist schlecht (ganzzahlig) durch 2 teilbar. mit glück rundet er gescheit und du hast aus abc die 2 "hälften" abc und cba gemacht, wobei cba in umgekehrter richtung gespeichert wird - und du kannst abc mit abc vergleichen und der sinn erfüllt sich. im schlechtesten fall versuchts du aber abc mit reverse(ba) zu vergleichen ^^ aber ich glaub, er rundet da ordentlich. 5/2=3 also indizes 0 bis 3-1 ergeben die erste hälfte und indizes length-1 bis length-3 die 2. hälfte. im notfall bei sowas mit nem überschaubaren bsp arbeiten und "abzählen" um zu schauen, obs stimmt ^^ mach ich auch immer  is zwar gefühlt wie rechnen mit der handabzählerei als hilfe, aber solange es klappt xD


----------



## boss3D (22. November 2012)

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

^^ Mein Plan war eigentlich, nicht auf gescheite Rundung durch den Compiler zu hoffen (abcba --> abc, cba), sondern bei strings mit ungerader Länge das Zeichen ganz in der Mitte zu ignorieren. 
Sollte ja problemlos möglich sein, nur den Teil links davon mit dem Teil rechts davon zu vergleichen. Das besagte Zeichen kommt ja nur 1x vor und muss daher mit nichts verglichen werden. 

Die Sache mit Index, Stellen, etc. verstehe ich schon. Ich sehe auch schon, wo bei uns die konkreten Unterschiede liegen. Du fängst in deinem Palindrom Code in der Schleife (die das gesamte Array durchläuft) bei i=0 an und musst somit entweder bis i<=length-1 oder i<length gehen. 

Bei mir sieht die Sache so aus:

```
[COLOR=seagreen]/* 
    Zerlege das zu überprüfende Wort in 2 Hälften und speichere jede in einem eigenen string.
    Der string, der die zweite Worthälfte bekommt, muss verkehrt herum angefüllt werden. 
    */    for (i=0, j=(length-1); i<(length/2), j>(length/2); i++, j--) {
        *(firstHalf+i)=*(checkString+i);
        *(secondHalf+i)=*(checkString+j);
    }
```
^^ So würde es gehen. Wenn ich das hier richtig verstehe, muss j length-1 sein, weil j bis (Index) 0 runterzählt?! Und bei den Abbruchbedingungen selbe Situation, wie bei dir: < (kleiner) length läuft ja auf's selbe hinaus, wie <= und length-1. Hier geht's offensichtlich um die Indexe. 

Wenn ich mich nicht ganz täusche, müsste auch mein Plan mit dem Ignorieren des Zeichens ganz in der Mitte bei ungeraden Arrays aufgehen?!


----------



## Freddycbv (23. November 2012)

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



boss3D schrieb:


> @ Freddycbv
> Ich glaube, in deiner ersten for-Schleife kannst du dir das i++ vor dem break sparen, weil du eh schon im Schleifenkopf inkrementierst.


Leider nicht, ist eine kleine Falle: Weil wenn ich bei Vorzeichen abbreche, ohne zu inkrementieren, ist er weiter unten in der Zahlensuche immer noch beim '+'/'-'. Dann würde er sofort abbrechen, und plötzlich ist auch "-300" oder "+70" falsch.
Also eine Stelle weiter, um zur 1.Zahl zu kommen


boss3D schrieb:


> Ich habe jetzt bei mir das else if (*(s+i)=='+') wieder reingetan und jetzt funktioniert's mit dem break anstelle von return result.


Aber nicht perfekt. Ich vermute, dass er so Zahlen wie "370-7" als -370 interpretiert. Deshalb hab ich in meinem letzten Post die Suche nach dem Vorzeichen nochmal komplett verändert.


boss3D schrieb:


> Was ich aber nicht ganz verstehe, ist, wo denn jetzt der 0er im Falle von ungültigen Zahlen herkommt. Zuerst war's logisch --> return result --> result=0. Aber jetzt?
> Ich vermute mal, irgendwie aus dieser Zeile: result = result*10+*(s+j)-48; ... aber wie kommt der Compiler da hin? Er geht ja nur in's else, wenn das if nicht stimmt. Und wenn das if nicht stimmt, wird doch die Anweisung darin gar nie ausgeführt?!
> ^^ Hach, immer diese Logiksachen. Bis bei mir da mal das Licht aufgeht ...


Ja, die If-Anweisung wird bei ungueltigen Zahlen nie ausgeführt! Er breaked sofort, und gibt dann sofort result zurück.
Result ist doch von Anfang an 0. So hast du das doch ganz oben initialisiert: int result = 0;
Ich glaub, das mit der Logik kommt mit der Zeit...  Ist ja auch nicht so einfach, immerhin redet kein Mensch in C


----------



## boss3D (23. November 2012)

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

Ok, danke! Das mit dem 0er ist jetzt auch klar und die Vorzeichensuche werde ich ebenfalls noch so weit verallgemeinern, dass nicht nur die 6 Arrays in der Angabe richtig umgewandelt werden. 

Bleibt nur noch eines, das mir heute Früh aufgefallen ist: Wieso ist ...

```
} else if ([COLOR=royalblue][B]![/B](*(s+j)[COLOR=royalblue][B]==[/B]'+' || *(s+j)[COLOR=royalblue][B]==[/B]'-') || startPos!=j) {
```
... semantisch nicht das selbe, wie ...

```
} else if ((*(s+j)[COLOR=royalblue][B]!=[/B]'+' || *(s+j)[COLOR=royalblue][B]!=[/B]'-') || startPos!=j) {
```
... ?
Jedenfalls stimmen die Ergebnisse nur bei der ersten Variante, nicht aber bei der zweiten. In beiden Fällen kann man sich das doch als "wenn-nicht-dann-mache" vorstellen?!


----------



## Freddycbv (23. November 2012)

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

Wenn das Zeichen nicht + oder - ist, dann breche ab.
*!*(*(s+j)*==*'+' || *(s+j)*==*'-') ist dasselbe wie (*(s+j)*!=*'+' && *(s+j)*!=*'-')

Ist ein bisschen schwer, aber man muss sich das einfach im Kopf vorstellen.

*(s+j)*==*'+' || *(s+j)*==*'-' => gibt true, wenn das Zeichen Plus oder Minus ist
*(s+j)*!=*'+' || *(s+j)*!=*'-' => gibt true, wenn das Zeichen (nicht Plus) oder (nicht Minus) ist; also IMMER
*(s+j)*!=*'+' && *(s+j)*!=*'-' => gibt true, wenn das Zeichen weder Plus noch Minus ist.

Einfach mal mit ein paar Werten im Kopf durchspielen, dann merkt man schon, obs passt oder nicht


----------



## boss3D (23. November 2012)

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

Aha, du meinst:
1 || 1 --> 1, wobei die 1er links und rechts vom logischen ODER eben von der Auswertung des Ausdrucks abhängen. Auf's && wäre ich übrigens sogar gekommen, nur habe ich es an der falschen Stelle ausprobiert (... && startPos!=j).  

Ist jetzt keine Frage, aber ich habe eben noch was entdeckt: Wenn du deine Schleife von for auf while umschreibst, brauchst du das i++ vor dem break wirklich nicht ...

```
while (*(s+i) != '\0') {
        if (*(s+i)=='+' || *(s+i) == '-'){
            if (*(s+i)=='-') {
                minus=1;
            }
            break;
        } else if (*(s+i)!=' ' && *(s+i)!='\t') {
            break;
        } 
        i++;
    }
```
^^ So funktioniert's bei mir (auch das "307-7"). 


Spoiler





```
#include <stdio.h>
#include <stdlib.h>

int convert(char s[]) {
    int i=0, j=0, minus=0, startPos=0, result=0;

    [COLOR=seagreen]/* Leerzeichen/Tabulatoren entfernen und Vorzeichen prüfen */    
    while (*(s+i) != '\0') {
        if (*(s+i)=='+' || *(s+i) == '-'){
            if (*(s+i)=='-') {
                minus=1;
            }
            break;
        } else if (*(s+i)!=' ' && *(s+i)!='\t') {
            break;
        } 
        i++;
    }
    
    [COLOR=seagreen]/* Prüfen auf Gültigkeit der Zahl und Rückrechnung von Dec nach Chr */    startPos=i;
    for (i; *(s+i) != '\0'; i++) {
        if (*(s+i)>=48 && *(s+i)<=57) { /* ASCII-Bereich der chars */
            result = result*10+*(s+i)-48;
        } else if ((*(s+i)!='+' && *(s+i)!='-') || startPos!=i) {
            break;
        }
    }

    [COLOR=seagreen]/* dem Vorzeichen entsprechende Rückgabe */    if (minus==1) {
        return -result;
    } else {
        return result;
    }
}

int main(void) {
    char *t1 = "012431234";
    char *t2 = "  -124";
    char *t3 = " +562";
    char *t4 = "13a";
    char *t5 = " a56 ";
    char *t6 = "     +13-56a";
    char *t7 = "  307-7";

    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t1, convert(t1), atoi(t1));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t2, convert(t2), atoi(t2));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t3, convert(t3), atoi(t3));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t4, convert(t4), atoi(t4));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t5, convert(t5), atoi(t5));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t6, convert(t6), atoi(t6));
    printf ("The value entered is %s. convert() liefert %d. atoi liefert %d.\n", t7, convert(t7), atoi(t7));

    return 0;
}
```


----------



## Freddycbv (23. November 2012)

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

ja, das liegt daran, dass ich weiter unten ja auch noch was umgebaut hatte 
Nämlich genau bei dem else if

```
// Prüfen auf Gültigkeit der Zahl und Rückrechnung von Dec nach Chr 
    for (i; *(s+i) != '\0'; i++) {
        if (*(s+i)>=48 && *(s+i)<=57) { // ASCII-Bereich der chars 
            result = result*10+*(s+i)-48;
        } [COLOR=darkred]else break; //abbrechen, falls keine Zahl    }
```
Ich fands so schöner, bzw besser getrennt: Die obere Schleife legt das Vorzeichen fest, und entfernt voranstehende Leerzeichen; und die unterer sucht nur nach Zahlen, und muss Vorzeichen und so nicht mehr berücksichtigen.

Deswegen brauche ich jetzt das i++ weiter oben, weil ich ja nicht mehr darauf prüfe, 
ob es ein Vorzeichen ist, das an erster Stelle steht.

Naja, ist jetzt eigentlich unwichtig...
wichtig ist ja nur, dass die Funktion jetzt richtig funktioniert


----------



## DarkMo (23. November 2012)

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

ahja, das logische 1*1 ^^

ein oder zu negieren endet in einem und (und umgekehrt). zu sagen !(a v b) entspricht !a ^ !b (v = oder zeichen, ^ = und zeichen. als eselsbrücke: das v kommt dem u nahe, man möcht also ans und denken, ergo isses das oder xD). gibt da noch mehr so regeln, wäre sicher ganz intressant für dich, dir das mal anzuschauen. du siehst ja, es bringt was (du hast es ja erstmal schön falsch gemacht ^^).


----------



## boss3D (23. November 2012)

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

^^ Ich sollte eigentlich binär rechnen können. v und ^ kenne ich, genau so wie das "halbe Plus" (habe kein passendes Symbol auf der Tastatur) für Negation. K.A. warum ich das hier übersehen habe. !(Irgendwas) ist halt wieder sowas, das ich nie benutze, weil ich != einfach wesentlich logischer finde. Dass man da dann bei den Verknüpfungen entsprechend umdenken muss, muss ich mir noch angewöhnen. 

Werde jetzt mal versuchen, meinen Ansatz für die Lauflängencodierung zu programmieren ...

Thanks für die Erklärungen beim Umwandlungsbeispiel. 

*[EDIT]*
@ DarkMo
Meine Idee für die Lauflängencodierung ist Rekursion, weil du gemeint hast, das sollte man eh immer wieder mal üben. 

Mein erster Anlauf ist auch gar nicht sooo schlecht:

```
#include <stdio.h>

double encode_runlength(char *s) {
    int i=0, j=1;

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

int decode_runlength(char *s) {

}

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

    encode_runlength(s);

    return 0;
}
```
^^ Nur bei drei Buchstaben (beim ersten B-Vorkommen,  das C- und das zweite D-Vorkommen) verzählt er sich noch. Aber den Fehler finde ich hoffentlich bald.

*[EDIT2]*
Hab's! j darf nicht um i erhöht werden, sondern immer nur um 1 --> j++. Die Decodierung wäre somit schon erledigt und der Code ist, zumindest für mich, wesentlich einfacher zu verstehen, als das (längere) Konstrukt, dass wir vor ein paar Wochen gebaut haben.

```
double encode_runlength(char *s) {
    int i=0, j=1;

    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;
            encode_runlength(s+i);
            break;
        }
        i++;
        j++;
    }
}
```


----------



## boss3D (23. November 2012)

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

Hm, schaut so weit schon ganz gut aus.  Nur die Berechnung der Verkürzung liefert noch bull**** (1431655765 %). Sehe den Fehler noch nicht (vermutlich irgendein double-int Konflikt) ...

```
#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, length=checkLength(s);
    double ratio=0.0, counter=0.0, count1=0.0, count2=0.0;

    while (*(s+i) != '\0') {
        if (*(s+i)!=*(s+j)) {
            if (j==1) {
                count1+=printf("%c", *(s+i));
            } else {
                count2+=printf("%c%d", *(s+i), j);
            }
            i=j;
            encode_runlength(s+i);
            break;
        }
        i++;
        j++;
    }

    counter=(count1+count2);
    ratio=((counter*100)/(double)length);

    return ratio;
}

int decode_runlength(char *s) {

}

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

    printf("Original:   %s\n", s);
    printf("Codiert:    ");
    printf("\nVerk%crzung: %d %%\n", 129, (100-encode_runlength(s)));
    printf("Decodiert:\n\n");

    return 0;
}
```
Ausgabe:




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



^^ Sobald die Verkürzung stimmt, bräuchte ich einen guten Tipp, wie ich denn nun die Encodierung (also, die verkürzte Zeichenkette) in die Decodier-Funktion rüberbringen kann. Ein Punkt der (strengen) Vorgaben ist nämlich folgender: Es darf ausschließlich mit dem Feld *s gearbeitet werden! 

Sobald also der komplette Inhalt encodiert ist, muss ich den Originalinhalt in der Funktion _encode_runlength()_ damit überschreiben und anschließend irgendwie *s nach _decode_runlength()_ verfrachten. Hier aber wieder das Problem: Die Vorgabe besagt, dass _encode_runlength()_ nur die Verkürzung zurückgeben darf und kein Feld, oder sonst was ...


----------



## DarkMo (23. November 2012)

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

hmm, auf jedenfall ein intressanter ansatz (also die rekursive lösung). du zählst also all gleichen buchstaben zusammen und am ende gibst dus aus, gehst in die nächste instanz (rekursiv) und machts mim nächsten buchstaben weiter. funktioniert, allerdings hast du nix "verwertbares" am ende. besser wärs meines erachtens nach, wenn du nen neuen string zusammen friemelst. dann haste a) was zum benutzen (ausgegeben aufm schirm isses nutzlos ^^) und b) kannste dann damit auch wieder dekodieren.

gut, wegen der ratio: das kann doch so garnich klappen ^^ hmm, gehn wir dein bsp (verkürzt) mal durch: AAAABBBCCCCCCCC
(beim funktionsaufruf ist die stelle des strings, auf die der zeiger zeigt, unterstrichen)

```
-> encode_runlength([U]A[/U]AAABBBCCCCCCCC)
    er findet 4 A's, i ist also 3 und j 4
    dann findet er das B, er gibt A4 aus und count2 wird 2
    rekursiver aufruf:
    -> encode_runlength(AAAA[U]B[/U]BBCCCCCCCC)
        er findet 3 B's, i ist also 2 und j 3
        dann findet er das C, er gibt B3 aus und count2 wird 2
        rekursiver aufruf:
        -> encode_runlength(AAAABBB[U]C[/U]CCCCCCC)
            er findet 8 C's, i ist also 7 und j 8
            dann findet er das ende, und hier is doch dann ... aso, die '\0' is ja ungleich dem 'C' ^^ ales klar*. also gibt er deswegen nochma C8 aus und count2 ist wieder 2
            der string is zuende, die counter werden zusammen gezählt** und ergeben 2
            die ratio wird errechnet: 2*100/15=13,333 und zurückgegeben
        <- 13,333
        der rückgabewert wird garnich gespeichert und weiter ausgewertet ><
        er nimmt sich nur wieder die selbe rechnung her für die ratio: wieder 2*100/15 und wieder 13,333
    <- 13,333
    hier natürlich das selbe und schlussendlich wird der wert an die main übergeben
<- 13,333
und die gibt 100-13,333 aus -> 86,667
```
anmerkung an der stelle: j is eigentlich unnötig. einfach s+i mit s+i+1 vergleichen sollte es auch tun ^^ man müsste aber glaube in der while dann auch s+j oder s+i+1 auf null prüfen! bei der if innendrin dann statt j==1 einfach auf i==0 getestet, fertig. spart ne variable und somit speicher ^^
* ok, beim weiter durchgehen is mir dann aufgefallen, wieso es klappt mit der abbruchbedingung in der while 
** 2 counter (bzw eben gar 3) is völlig sinnbefreit  einer reicht hier vollkommen

gut, ok. wir sehen, rein theoretisch sollte er wenigstens ne sinnvolle %zahl ausgeben. wieso da jetz son unfug rauskommt, puh. vllt ergibt ja count1+=printf("%c", *(s+i)); hier mist? printf gibt int zurück und count1 is double. aber ich kann mir nich so ganz vorstellen, das er das ned gebacken bekommt *grübel* wär mMn aber der einzige knackpunkt hierbei.

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%

du siehst - so kommt nur mist raus. besser isses also wenn du die gekürzte länge zurück gibst und immer addierst: counter += encode_runlength(s+i); und dann in der main startest du das ganze genauso und errechnest hier die ratio aus ursprungslänge und counter -> eben jenes (double)counter*100/length was in unserem bsp dem 6*100/13 entspräche und somit ein vernünftiges ergebnis erzielt.

ein passender code könnte also sein:

```
#include <stdio.h>

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

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

    while (*(s+i) != '\0') {
        if (*(s+i)!=*(s+i+1)) {
            if (i==0) counter += printf("%c", *(s+i));
            else counter += printf("%c%d", *(s+i), i+1); // die selbsterstellte länge erfassen
            counter += encode_runlength(s+i); // und die länge der anderen rekursiv-instanzen dazuzählen
            break;
        }
        i++;
    }

    return counter;
}

int main(void) {
    char *s = "AAAABBBCCCCCCCCDEABBBBDDDDDDDD";
    int counter, length = checkLength(s);
    double ratio;

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

    return 0;
}
```


----------



## boss3D (23. November 2012)

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

^^    

Auf deine Lösung bin ich auch selbst schon gekommen und ich kann mir auch einigermaßen vorstellen, wo der blödsinnige Wert in meiner jetzigen Version herkommt. Ich habe nämlich mal testweise die jeweiligen Werte für count1, count2 und counter ausgeben lassen:




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



count1 und count2 habe in jedem Schleifendurchlauf den richtigen Wert und aufsummiert würde sich tatsächlich 13 ergeben. Das Problem: Es wird nur leider nie aufsummiert (warum auch immer) und somit bleibt counter 0. Wenn man sich das jetzt in der Rechnung anschaut, haben wir (0*100)/30. Tja, das kann nichts Gescheites ergeben ...

Das eigentliche Problem ist aber, *dass die Vorgaben in der Angabe *(siehe Absatz in/nach Zitat)* keinen anderen Weg zulassen* und das versuche ich euch schon seit 3 Wochen, oder wann auch immer wir mit dem Beispiel gestartet haben, zu sagen!!!  


boss3D schrieb:


> bräuchte ich einen guten Tipp, wie ich denn nun  die Encodierung (also, die verkürzte Zeichenkette) in die  Decodier-Funktion rüberbringen kann. Ein Punkt der (strengen) Vorgaben  ist nämlich folgender: Es darf ausschließlich mit dem Feld *s gearbeitet  werden!
> 
> Sobald also der komplette Inhalt encodiert ist, muss  ich den Originalinhalt in der Funktion _encode_runlength()_ damit  überschreiben und anschließend irgendwie *s nach  _decode_runlength()_ verfrachten. Hier aber wieder das Problem: Die  Vorgabe besagt, dass _encode_runlength()_ nur die Verkürzung  zurückgeben darf und kein Feld, oder sonst was ...


Klar, wenn's nach mir ginge, würde ich zack-bum ein weiteres Feld machen und den codierten string darin speichern. Dann string weiter an _decode_runlength()_ --> wieder decodieren --> fertig. NUR: Darf ich ja nicht! Es darf *ausschließlich mit *s* *gearbeitet* werden.
Und als ob das noch nicht Restriktion genug wäre: Die Funktion _encode_runlength()_ darf NUR die *brechnete Ratio zurückgeben*, nichts anderes!

^^ Bitte bei sämtlichen weiteren Tipps das berücksichtigen. Wie gesagt, mir fallen selbst zig Wege ein, die Aufgabe zu lösen, nur nutzen die uns in dem Fall leider nichts ...
*
[EDIT]*
Hier die Aufgabenstellung. Glaub's zwar nicht, aber vielleicht interpretiere ich das Ganze ja auch falsch?!




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



_PS: Dass ich mich noch um Groß-/Kleinschreibung und übergabe des Strings an die main kümmern muss, weiß ich, nur das will ich mir für den Schluss aufheben._ 

*[EDIT2]*
Habe eben einfach "zum Spaß" jetzt mal deine Version ausprobiert (copy paste in's Visual Studio). Ist aber eine Endlosschleife, die nur "A"s ausgibt. Einfügen geschwungener Klammern, um eventuelle Missinterpretation von zusammengehörigen Befehlen durch den Compiler zu vermeiden, hat auch nichts gebracht. Ich glaube, ganz so weit kann man das dann doch nicht vereinfachen. Was jetzt nur die Codierung selbst betrifft, bleibe ich lieber bei i und j.

Und wenn ich nur die Aufsummierungen nach deinem Schema in meinen Code übernehme, bleibt counter genau 0. Daher: return counter ist praktisch return 0 ... und damit bin ich in etwa soweit, wie heute Nachmittag (siehe erstes Bild in diesem Posting).


----------



## DarkMo (24. November 2012)

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

gut, dann bleibt ansich nur, auf rekursion zu verzichten (wie ichs dir hier eh geraten hätte) und call-by-reference zu verwenden. eine funktion kann nur einen rückgabe-wert haben, und das soll ja scheinbar die ratio sein. wenn du aber *s an sich verändern sollst, muss das ja auch zurück gegeben werden. das klappt ganz "simpel", indem man nicht den wert einer variablen übergibt (die funktionslokale variable kopiert den wert nur), sondern die referenz darauf (einen zeiger). also eigentlich müsste das scho fast klappen *grübel* ^^

nur um die theorie nochmal abzureisen, damit wir auch wissen, wovon wir sprechen:

```
void fkt(int i) {
    i++;
    printf("fkt: %d\n", i);
}

void main(void) {
    int a = 2;
    printf("main: %d\n", a);
    fkt(a);
    printf("main: %d\n", a);
}
```
Ausgabe:
main: 2
fkt: 3
main: 2

in der funktion wird der kopierte wert verändert, nich aber der originale. grund: a aus der main hat die speicheradresse 12345 und i aus fkt is ne andere, neue variable mit der adresse 743375. beim übergeben von a an fkt wird also der wert von a (an adresse 12345) an die adresse von i (743375) kopiert. man verändert mit i also nur die kopie, das original bleibt unberührt.

man kann jetz natürlich den rückgabewert nutzen, was dann so aussähe:

```
int fkt(int i) {
    i++;
    printf("fkt: %d\n", i);
    return i;
}

void main(void) {
    int a = 2;
    printf("main: %d\n", a);
    a = fkt(a);
    printf("main: %d\n", a);
}
```
Ausgabe:
main: 2
fkt: 3
main: 3

aber dann bearbeitet man immernoch nur eine kopie und überschreibt das original dann mit dem wert der kopie. gut, solange der erfolg eintritt, den man will kanns ja erstma wurscht sein. wir haben ja nun aber eben das problem, dass wir keine kopie von a übergeben wollen, sondern a selbst, um dann den rückgabewert für die ratio reservieren/nutzen zu können. das is dann dass call-by-reference. das bisherige war call-by-value.

bei call-by-reference übergibt man nicht den wert von a, sondern den zeiger auf a. mit diesem zeiger kann man nun direkt a aus der funktion heraus verändern:

```
void fkt(int &i) {
    i++;
    printf("fkt: %d\n", i);
}

void main(void) {
    int a = 2;
    printf("main: %d\n", a);
    fkt(a);
    printf("main: %d\n", a);
}
```
Ausgabe:
main: 2
fkt: 3
main: 3

is im endeffekt wieder bsp 1, nur mit nem & vorm funktionsparameter ^^
hier auch nochmal ein intressanter "bericht": call-by-reference @ C/C++ - tutorials.de: Tutorial, Forum, Anleitung & Hilfe is nich allzulang. hier wird auch auf den unterschied zw &var und *var eingegangen. das erste (&) ist c++ und "richtiges" call by reference, das zweite (*) ist die frühe version vom reinen c. nachteil ist wohl, dass man die adresse des pointers nicht ändern kann, nur den inhalt. ich versteh das gerade so: wenn du in der funktion s++ machst um den ointer weiter zuschieben, so geschieht das wiederrum nur lokal. du kannst aber dennoch global die adresswerte ändern - das würde uns ansich auch völlig reichen *denk*

probieren wirs mal ^^
....
............
viele monde später: ich gebs erstma auf >< hab noch Pointer-to-Pointer and Reference-to-Pointer gefunden, was glaub ich prinzipiell ganz gut is, aber irgendwie schmeisst mein visual nur fehler :/


----------



## boss3D (24. November 2012)

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

Call-by-value, call-by-reference, ... kenne ich alles. Ist ja nicht das erste Beispiel, wo wir mit Zeigern arbeiten. 

Der Knackpunkt dürfte hier wirklich die Rekursion sein. Wir müssen einen Weg finden, die Zeichenkette nicht in mehreren Anläufen zu codieren, sondern in einem und mit dem Ergebnis dann sofort den Inhalt des Zeigers (also das, was an der Adresse, die er referenziert, steht), was ja die originale Zeichenkette ist, zu überschreiben. Wenn ich dann *s ganz normal in _decode_runlength()_ ausgeben lasse, müsste er mir die codierte Version anzeigen, weil ja die dann an der Adresse von s gespeichert sein müsste. So könnte ich dann auch damit weiterarbeiten. 
Interessanter Ansatz, wenn ich das richtig verstanden habe ... 

Was mir jedoch "Spanisch" vorkommt, ist &irgendwas in einem Funktionsheader. So was haben wir nie gelernt und ich habe sowas auch noch nie gesehen. Es reicht doch, wenn ich mit * auf die Adresse zeige?! Werde mir morgen (also heute später ) deine Links ansehen und dann das ganze mal von rekursiv auf iterativ umschreiben. Wenn dann erst einmal die Codierung und die Berechnung/Rückgabe von ratio läuft, überlegen wir weiter ...

*[EDIT]*
Nur ein Gedankenspiel: Rein theoretisch müsste es doch auch mit dem rekursiven Ansatz gehen, und zwar so --> Nach jeder Runde ist eine Buchstabenfolge codiert. Am Ende jeder Runde überschreibe ich nun im Originalstring immer die beiden Indexstellen der ersten beiden Vorkommen des jeweiligen Buchstaben. 

Z.B.: *s = AAAABBBCCCCC --> _encode_runlength()_ läuft --> vor dem nächsten rekursiven Aufruf --> i=0(Buchstabe), j=1(Zahl); *(s+i) und *(s+j) = Ergebnis des Durchlaufs --> *s = A2xxBBBCCC (xx weil ich mir nicht ganz sicher bin, was für die beiden Index-Stellen ausgegeben werden würde) --> in der nächsten Runde würde dann nach der Berechnung xx mit B3 überschrieben werden --> usw. ...

^^ Somit würde ich zwar bereits Werte an der Speicheradresse von s verändern obwohl andere Werte an der selben Speicheradresse noch zur Auswertung benötigt werden, aber da die Vorkommensberechnung jedes Buchstabens eh immer bei einem Index startet, der nach dem überschriebenen liegt, sollten sich Zuweisung(=Überschreibung) und Berechnung nicht in's Gehäge kommen?!

Das muss ich "zum Spaß" direkt mal ausprobieren. 
Dürfte aber relativ kompliziert zu programmieren sein, falls es überhaupt geht. Was hälst du davon?
*
[EDIT2]*
So, das ^^ oben habe ich nicht hingekriegt. Ist aber auch egal; habe jetzt nämlich eine iterative Lösung ...



Spoiler





```
#include <stdio.h>

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

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

    return length;
}

[COLOR=royalblue][B]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;
        }
        i++;
        j++;    
    }

    return ratio;
}[/B]
int decode_runlength(char *s) {
    printf("%s\n", s);
}

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

    printf("Original:   %s\n", s);
    printf("Codiert:    ");
    printf("\nVerk%crzung: %d %%\n", 129, encode_runlength(s));
    printf("Decodiert:\n\n");
    decode_runlength(s);

    return 0;
}
```



Jetzt müsste ich irgendwie den codierten String an der Adresse, auf die *s zeigt, speichern, um damit in der Decodierfunktion weiterarbeiten zu können ...


----------



## DarkMo (24. November 2012)

*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:


DarkMo schrieb:


> 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:


```
[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.

```
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|pder 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:

```
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|qso, 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:

```
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,qwobei ich hier eben grad nich weis, ob das schon der springende punkt ist. denn im urpsungszenario siehts ja so aus:

```
void fkt(int &q) {}
void main(void) {
    int i = 15;
    fkt(i);
}
```


Adresse|Wert|Var-Name
123|15|i,qalso 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:

```
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|pIntdas 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:

```
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|ppInthmm. 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|ppIntwobei 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 ><

```
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, rpInthier 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


----------



## boss3D (24. November 2012)

*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:

```
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.


----------



## DarkMo (24. November 2012)

*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:

```
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:

```
#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?


----------



## boss3D (24. November 2012)

*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:

```
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:


Spoiler





```
#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:

```
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++;
    }
}
```
^^ ???


----------



## DarkMo (24. November 2012)

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



boss3D schrieb:


> ^^ 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.


----------



## boss3D (24. November 2012)

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



DarkMo schrieb:


> 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]*

```
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 ...

```
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!!!


----------



## DarkMo (24. November 2012)

*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:

```
#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;
}
```


----------



## boss3D (24. November 2012)

*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 ...




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



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 ?!


----------



## DarkMo (24. November 2012)

*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 

```
#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;
}
```


----------



## boss3D (24. November 2012)

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

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

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!


----------



## DarkMo (24. November 2012)

*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


----------



## boss3D (24. November 2012)

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



DarkMo schrieb:


> 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?




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



^^ 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 ...


Spoiler





```
#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?




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



*[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:

```
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++;
    }
}
```



			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



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



			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



*Wo sind meine A4, B3, etc.???   
*


----------



## DarkMo (25. November 2012)

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



boss3D schrieb:


> *Wo sind meine A4, B3, etc.???   *





> ```
> ...
> *(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 

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:

```
11 11 11 1 1 1 11 11
A4 B3 C8 D E A B4 D8
```


----------



## boss3D (25. November 2012)

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

^^ Ahhh ... 

Okay, das bringt mich schon mal 50 % weiter. 

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




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



```
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 ... 
Dabei ist doch j-count in jeder Runde genau das, wo die Zahl berechnet wird?!

*[EDIT]*
Hab's schon:

```
*(s+k+1)=(char)(j-count)+48;
```



			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



^^ 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:

```
*(s+(int)ratio)='\0';
```



			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



Ist ja jetzt wirklich nur mehr Zuweisen, Zuweisen, Zuweisen ...


----------



## DarkMo (25. November 2012)

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



boss3D schrieb:


> *[EDIT]*
> Hab's schon:
> 
> ```
> ...


jaaaa, an diesem kleinen ding hing ich auch erst xD dann fiel es mir wie schuppen von den augen ^^


boss3D schrieb:


> ^^ 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


----------



## boss3D (25. November 2012)

*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:


Spoiler





```
#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;
}
```






			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



Hilfe, bitte?!

Ein neues Ende könnte ich dem String ja recht simpel zuweisen:

```
*(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.


----------



## boss3D (25. November 2012)

*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:




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        




```
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;
}
```


----------



## DarkMo (25. November 2012)

*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:

```
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));
```


----------



## boss3D (25. November 2012)

*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. 


DarkMo schrieb:


> 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.


----------



## DarkMo (25. November 2012)

*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


----------



## boss3D (25. November 2012)

*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:

```
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._


----------



## DarkMo (25. November 2012)

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

wegen von hinten vs. von vorne (A4B3C8DEAB3D8):
von hinten muss ich erst das leerzeichen um 6 verschieben -> 1
dann die 7 restlichen D's schreiben (dabei die 8 überschreiben)
dann diese 8 D's 1 nach hinten schieben um platz für die B's zu machen -> 1+8 verschiebungen = 9
die 2 B's schreiben (die 3 dabei überschreiben)
A, E und D müssen nich verschoben werden
dann 8 D's, 3 B's, A, E und D 7 nach hinten schieben, um den C's platz zu machen -> 9+8+3+1+1+1 = 23
die 7 C's schreiben (die 8 dabei überschreiben)
dann 8 D's, 3 B's, A, E, D und 8 C's 1 nach hinten schieben, um den B's platz zu machen -> 23+8+3+1+1+1+8 = 45
die 2 B's schreiben (die 3 dabei überschreiben)
und zu guter letzt 8 D's, 3 B's, A, E, D, 8 C's und 3 B's um 2 verschieben für die A's -> 45+8+3+1+1+1+8+3 = 70

wir haben also von hinten her 70 verschiebungen durchzuführen (bei diesem winzigen schnipsel - an ne komplette datei will ich garnich denken ). jetz mal, wenn man von vorne an die sache ran geht (wieder A4B3C8DEAB3D8):
B3C8DEAB3D8\0 um 2 nach hinten verschieben -> 12 verschiebungen
C8DEAB3D8\0 um 1 nach hinten verschieben -> 12+10 = 22
DEAB3D8\0 um 6 nach hinten verschieben -> 22+8 = 30
für DEA -> brauch nix verschoben zu werden
D8\0 um 1 nach hinten verschieben -> 30+3 = 33

fertig. nun kann man noch die \0 am ende ignorieren und erst am ende schreiben, da spart man beim ersten bsp eine verschiebung - also bleiben 69 - und beim 2. spart man sich 4 - reduziert sich also auf 29. stehen also 69 verschiebungen 29 gegenüber. ne reduktion um gerademal 100-(29*100/69) = rund 58%  performancegewinn in der region is glaube nich zu verachten


----------



## boss3D (25. November 2012)

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

^^ Ok, jetzt glaub ich's dir ( ), aber mir ist das dann doch zu kompliziert mit der Pointer-Herumzeigerei und Verschieberei beim von-vorne-Anfangen (ohne, dass ich was überschreibe, das ich erst noch auswerten muss). 

Habe jetzt meine Decodier-Funktion noch einmal neu geschrieben und auch den restlichen Code optimiert. Bin jetzt auch zu 99 % fertig. Mir bleibt nur ein kleines Problem: Ich komme beim von-hinten-Ansatz vorne um 1 über die Feldgrenze hinaus (für's allererste A), deswegen meckert er (quasi "Index -1"). Das muss ich noch lösen ...




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



*[EDIT]*
Hab's! Das j in der Schleife hat zu viel Druck gemacht von hinten (<-- was für eine Ausdrucksweise). 
j=0; j<count; j++ und alles passt.


Spoiler





```
#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;

    [COLOR=seagreen]/* Codieren des Original-Strings: */    while (*(s+i) != '\0') {
        if (*(s+i)!=*(s+j)) { [COLOR=seagreen]/* Sobald Buchstabe nicht mehr gleich seinem Nachfolger ist, prüfe: */            if ((j-count)==1) { [COLOR=seagreen]/* Einmaliges Vorkommen? */                *(s+k)=*(s+i); [COLOR=seagreen]/* Überschreibe Feld von vorne beginnend mit Buchstaben ... */                k++; [COLOR=seagreen]/* ... und springe im Index um 1 weiter. */                count=j;
            } else { [COLOR=seagreen]/* Mehrmaliges Vorkommen? */                *(s+k)=*(s+i); [COLOR=seagreen]/* Überschreibe Feld von vorne beginnend mit Buchstaben ... */                *(s+k+1)=(char)(j-count)+48; [COLOR=seagreen]/* ... und füge immer einen Index weiter das berechnete Vorkommen ein. */                k+=2; [COLOR=seagreen]/* Dann springe 2 Felder weiter, um an die nächste zu überschreibende Stelle zu gelangen. */                count=j;
                ratio=(double)k; [COLOR=seagreen]/* ratio enthält am Ende der Schleife die Länge der Codierung. */                *(s+(int)ratio)='\0'; [COLOR=seagreen]/* Hänge an die Codierung noch eine Nullterminierung an. */            }            
        }
        i++;
        j++;
    }

    printf("%s", s); [COLOR=seagreen]/* Ausgabe: Codierter String */
    return ((ratio*100)/(double)length);
}

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

    [COLOR=seagreen]/* Ermittle Länge des originalen Strings: */    while (*(s+i)!='\0') {
        if (*(s+i+1)>=50 && *(s+i+1)<=57) {
            count=(*(s+i+1)-48);
            i+=2;
            length+=count;
        } else {
            i++;
            length++;
        }
    }
    
    [COLOR=seagreen]/* Decodieren des codierten Strings: */    i=checkLength(s);
    count=0;
    *(s+length)='\0';
    while (i>0) {
        if (*(s+i)>=50 && *(s+i)<=57) {
            count=(*(s+i)-48);
            for (j=0; j<count; j++) {
                *(s+(length-j))=*(s+(i-1));
            }
            length-=count;
            i-=2;
        } else {
            *(s+(length-1))=*(s+i);
            length--;
            i--;
        }
    }
    
    printf("%s", s); [COLOR=seagreen]/* Ausgabe: Decodierter String */ 

    return 0;
}

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

   [COLOR=seagreen] /* Kleinbuchstaben in Großbuchstaben umwandeln */    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;
}
```



Jetzt kommt die Feuerprobe für den Code: Muss das Ganze jetzt noch schnell auf "Parameter-an-main-übergeben" (argc, *argv[]) umschreiben und dann werden wir sehen, ob's wirklich für jeden String (mit Buchstabenvorkommen zwischen 0 und 9) geht. 

*[EDIT2]*
Habe gerade noch einen kleinen Fehler bei den einzelnen Buchstaben entdeckt. Der muss noch raus ...
So, jetzt passt's:

```
*(s+length)=*(s+i);
```


----------



## boss3D (25. November 2012)

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

*** FERTIG ***

Und es funktioniert tatsächlich für alles im Rahmen von 0 bis 9.  


Spoiler





```
#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;

    [COLOR=seagreen]/* Codieren des Original-Strings: */    while (*(s+i) != '\0') {
        if (*(s+i)!=*(s+j)) { [COLOR=seagreen]/* Sobald Buchstabe nicht mehr gleich seinem Nachfolger ist, prüfe: */            if ((j-count)==1) { [COLOR=seagreen]/* Einmaliges Vorkommen? */                *(s+k)=*(s+i); [COLOR=seagreen]/* Überschreibe Feld von vorne beginnend mit Buchstaben ... */                k++; [COLOR=seagreen]/* ... und springe im Index um 1 weiter. */                count=j;
            } else { [COLOR=seagreen]/* Mehrmaliges Vorkommen? */                *(s+k)=*(s+i); [COLOR=seagreen]/* Überschreibe Feld von vorne beginnend mit Buchstaben ... */                *(s+k+1)=(char)(j-count)+48; [COLOR=seagreen]/* ... und füge immer einen Index weiter das berechnete Vorkommen ein. */                k+=2; [COLOR=seagreen]/* Dann springe 2 Felder weiter, um an die nächste zu überschreibende Stelle zu gelangen. */                count=j;
                ratio=(double)k; [COLOR=seagreen]/* ratio enthält am Ende der Schleife die Länge der Codierung. */                *(s+(int)ratio)='\0'; [COLOR=seagreen]/* Hänge an die Codierung noch eine Nullterminierung an. */            }            
        }
        i++;
        j++;
    }

    printf("%s", s);[COLOR=seagreen] /* Ausgabe: Codierter String */
    return ((ratio*100)/(double)length);
}

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

   [COLOR=seagreen] /* Ermittle Länge des originalen Strings: */    while (*(s+i)!='\0') {
        if (*(s+i+1)>=50 && *(s+i+1)<=57) {
            count=(*(s+i+1)-48);
            i+=2;
            length+=count;
        } else {
            i++;
            length++;
        }
    }
    
    [COLOR=seagreen]/* Decodieren des codierten Strings: */    i=checkLength(s); [COLOR=seagreen]/* i = Länge des codierten Strings. */    count=0;
    *(s+length)='\0';[COLOR=seagreen] /* length = Länge des Original-Strings. */    while (i>0) { [COLOR=seagreen]/* Es muss von hinten mit dem Überschreiben begonnen werden, um nicht was zu überschreiben, das noch ausgewertet werden muss. */        if (*(s+i)>=50 && *(s+i)<=57) { [COLOR=seagreen]/* Überprüfen auf Zahlen. */            count=(*(s+i)-48); [COLOR=seagreen]/* Wenn gefunden, wird Zahl in count gespeichert. */            for (j=0; j<count; j++) {
                *(s+(length-j))=*(s+(i-1));[COLOR=seagreen] /* Überschreiben der Feldelements mit dem ersten von hinten gefundenen Buchstaben entsprechend seiner Anzahl. */            }
            length-=count; [COLOR=seagreen]/* Länge reduziert sich um Anzahl der geschriebenen Buchstaben (bei Mehrfachvorkommen) */            i-=2; [COLOR=seagreen]/* Ein Buchstabe und seine Zahl wurde ausgewertet; überspringe sie also. */        } else {
            *(s+length)=*(s+i); [COLOR=seagreen]/* Bei Einfachvorkommen, einfache Zuweisung des Buchstabens. */            length--;[COLOR=seagreen] /* Länge und Zähler reduzieren sich um 1. */            i--;
        }
    }
    
    printf("%s", s); [COLOR=seagreen]/* Ausgabe: Decodierter String */
    return 0;
}

int main(int argc, char *argv[]) {
    char *s = argv[1];
    int i=0;

   [COLOR=seagreen] /* Kleinbuchstaben in Großbuchstaben umwandeln */    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;
}
```



^^ Witzig nur, dass jetzt argv[1] eigentlich wieder in *s (man beachte den Stern) gespeichert wird und wir dann trotzdem problemlos damit arbeiten können.

-------------------------------
Bleibt nur noch eine allerletzte Aufgabe, dann hätten wir alles durchprogrammiert, was ich an Übungs-Material hier habe ... 




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



^^ Hier das Problem, dass ich mit der Imaginärzahl, oder wie auch immer i in Mathe heißt, gar nichts anfangen kann. Das stand wohl nicht auf dem Lehrplan des Gymnasiums, das ich vor Jahren besucht habe?!
Und wenn mit Datenstruktur "typedef struct {} Name;" gemeint ist, dann meine Frage: für was? Soll ich Werte einlesen und da rein speichern, oder ist das dann für die Rechenergebnisse der Funktionen?

_PS: Werde selber erst morgen mit dem neuen Beispiel anfangen, also heute bloß kein Stress mehr._


----------



## bingo88 (25. November 2012)

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

Zu komplexen Zahlen allgemein: Komplexe Zahl
Die Rechenregeln werden für dich interessant sein, wenn du die implementieren sollst.

Zur Struktur: Da eine komplexe Zahl im wesentlich aus zwei Komponenten besteht (Real- und Imaginärteil), macht es Sinn diese zusammen in einer Struktur zu speichern. Eine Variable vom Typ dieser Struktur entspricht dann genau einer komplexen Zahl. Damit kannst du dan rumrechnen oder sonstwas machen ^^


----------



## boss3D (28. November 2012)

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

^^ Bin gerade dabei, mich da einzulesen. Ich habe auch schon vorsichtig angefangen, das Grundgerüst für die Aufgabe zu erstellen, allerdings habe ich starke Zweifel, dass die "entsprechende Datenstruktur" (wenn sie denn überhaupt so ausschauen soll, wie bei mir) global deklariert werden muss. Mache ich es allerdings lokal in der main, unterwellt er mir im VS komplex_t *k rot ...

```
#include <stdio.h>

[COLOR=royalblue][B]typedef struct komplex_t {
    double a;
    double b;
};[/B]
void print_komplex(komplex_t *k) {

}

komplex_t add_k(komplex_t *k1, komplex_t *k2) {

}

komplex_t sub_k(komplex_t *k1, komplex_t *k2) {

}

komplex_t mul_k(komplex_t *k1, komplex_t *k2) {

}

komplex_t div_k(komplex_t *k1, komplex_t *k2) {

}

int main(void) {

    return 0;
}
```



> In der main()-Funktion sollen verschiedene komplexe Zahlen (z.B. 0 0, 1.23 0, 0 3.14, -2.34 1, -3 4, 1
> 3, 1 1) definiert und damit die geschriebenen Funktionen getestet werden.


Ob das jetzt heißen soll, dass ich in der main 7 structs mit dem jeweiligen Zahlenpaar als Inhalt anlegen soll, bin ich mir auch noch nicht sicher ...

Der Zeiger *k zeigt auf ein Element aus dem Inhalt von komplex_t (das ein struct sein soll?!) und nicht auf das ganze struct, oder? Habe noch nie mit sowas gearbeitet, also sorry, wenn die Fragen aus eurer Sicht dumm klingen.


----------



## bingo88 (28. November 2012)

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

Da du mit dem struct einen neuen Datentyp einführen willst, musst du das schon mehr oder weniger "global" bekannt machen.


```
/* ist jetzt ohne typedef, mit typedef sparst du dir das "struct" wenn du eine Variable anlegen wills */
struct MyStruct
{
    int v1;
    int v2;
    double v3;
};

void fillStruct(struct MyStruct *ps)
{
    ps->v1 = 10;
    ps->v2 = 100;
    ps->v3 = -0.5f;
}

int main(int argc, char *argv[])
{
    /* Variablen anlegen */
    struct MyStruct s1, s2;
   
    fillStruct(&s1);
    fillStruct(&s2);

    return 0;
}
```
Ist jetzt nicht so ein mega sinnvolles Beispiel ^^


----------



## boss3D (28. November 2012)

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

^^ Habe jetzt mal ein Bischen recherchiert und dabei rausgefunden, dass das Befüllen des structs komplex_t auch einfach mit dem . oder dem -> Operator gehen müsste. Was ich halt nicht verstehe, ist, auf was genau der Zeiger *k zeigen soll ...

*[EDIT]*
Gerade rausgefunden: Die Wertzuweisung und Ausgabe würde so funktionieren:

```
#include <stdio.h>

typedef struct {
    double a;
    double b;
} komplex_t;

void print_komplex(komplex_t *k) {
    printf("( %.2lf %.2lf )\n", *k, *k);
}

komplex_t add_k(komplex_t *k1, komplex_t *k2) {

}

komplex_t sub_k(komplex_t *k1, komplex_t *k2) {

}

komplex_t mul_k(komplex_t *k1, komplex_t *k2) {
    
}

komplex_t div_k(komplex_t *k1, komplex_t *k2) {

}

int main(void) {
    komplex_t *k;
    komplex_t komplex_1 = { 1.23, 0.0 };
    k=&komplex_1;

    print_komplex(k);

    return 0;
}
```
Jetzt bin ich aber noch mehr verwirrt: Der Zeiger *k müsste jetzt eigentlich auf die gesamte Struktur komplex_1 (ist ja vom Aufbau ident mit komplex_t) zeigen. Wieso muss ich dann aber im printf 2 mal den Zeiger einsetzen, um den gesamten Strukturinhalt ausgeben zu lassen? Und v.a.: Wieso bekomme ich die 2 verschiedenen Werte über den selben Zeiger (der ja nach meiner Logik ohnehin auf das gesamte struct zeigen sollte)?


----------



## DarkMo (28. November 2012)

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

na deine struct is nen selbst geschriebener datentyp wie int zum bsp. du kannst nun also variablen vom typ deines structs anlegen. und auf genau diese zeigt dann der zeiger.


----------



## boss3D (28. November 2012)

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

^^ Habe vor 3 Minuten eben genau das rausgefunden (siehe aktualisierter Code im vorigen Posting). Dass der Zeiger auf die erstellte Variable (die ja vom Aufbau wie das struct ausschauen müsste) zeigen sollte, hätte auch ich mir erwartet, aber anscheinend zeigt er auf alle Werte im struct (anstatt auf das gesamte struct)?! --> bitte auch meine Fragen im vorigen Posting beachten ...

*[EDIT]*
So geht's wohl auch:

```
void print_komplex(komplex_t *k) {
    printf("( %.2lf %.2lf )\n", *k);
}
```
Nur wenn der eine Zeiger *k wirklich auf das gesamte struct zeigt, wie soll ich dann anhand von *k zwischen den beiden Werten unterscheiden? Ich muss ja beispielsweise eine Überprüfen einbauen, ob der Real- od. der Imaginärteil gleich 0 ist. Nur if (*(k+0)==0  || *(k+1)==0) { spielt's nicht. Da meckert der Compiler ...

BTW: Die 4 Rechenfunktionen habe alle 2 Zeiger in der Parameterdeklarationsliste. Nur, wenn eh jeder der beiden Zeiger auf das gesamte struct zeigt, wofür brauche ich dann 2?


----------



## Dragonix (28. November 2012)

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



boss3D schrieb:


> ^^ Habe vor 3 Minuten eben genau das rausgefunden (siehe aktualisierter Code im vorigen Posting). Dass der Zeiger auf die erstellte Variable (die ja vom Aufbau wie das struct ausschauen müsste) zeigen sollte, hätte auch ich mir erwartet, aber anscheinend zeigt er auf alle Werte im struct (anstatt auf das gesamte struct)?! --> bitte auch meine Fragen im vorigen Posting beachten ...
> 
> *[EDIT]*
> So geht's wohl auch:
> ...


 
Ich glaube, du solltest dir erstmal das hier Galileo Computing :: C von A bis Z – 15 Strukturen (bzw halt was ähnliches) durchlesen - hier structs zu erklären würde dann doch den Rahmen sprengen...

Und falls das

```
printf("( %.2lf %.2lf )\n", *k);
```
wirklich funktioniert (was ich nichteinmal komplett bestreiten möchte), dann bezweifle ich, dass es das tut was du vermutest das es tut - aufjedenfall ist das ganz arg doll böse und das solltest vermeiden.
Richtig wäre sowas in der Art (*k).real oder (schöner) k->real (-> dereferenziert erst und greift dann auf das angegebene Element zu, steht aber alles in obigem Link). Andererseits meine ich, dass ich mir damit schön das ganze Programm abschiesse - printf erwartet eben zwei Argumente. In diesem Kontext ist übrigens auch das http://en.wikipedia.org/wiki/Stdarg.h interessant, falls nicht bekannt.


----------



## boss3D (28. November 2012)

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

^^ Den Galileo Computing Artikel habe ich gestern schon überflogen (brauche ja erst einmal nur die korrekte Syntax. An die Semantik geht's wenn alle nötigen Variablen definiert sind). 

Ja, das printf, das du zitierst, hatte wirklich genau das gemacht, was ich mir erwartet habe: Der Zeiger *k zeigt auf struct komplex_t, dessen beide Werte direkt hintereinander im Speicher liegen und somit "glücklicherweise" auch hintereinander ausgegeben wurden. 
Dass das "doll böse" ist, glaube ich dir aber sofort.

Habe jetzt die Ausgabe so umgeschrieben:

```
printf("( %.2lf %.2lf )\n", (*k).a, (*k).b);
```
Ich glaube jetzt auch, verstanden zu haben, warum die Rechenfunktionen 2 Zeiger brauchen, mit denen ich ja auf insg. 4 Elemente zugreifen kann: Ich habe nämlich ursprünglich angenommen, dass 0 und 0, oder 1.23 und 0 usw. bereits jeweils ein Zahlenpaar ist, mit dem ich rechnen soll. Es dürfte aber vielmehr so sein, dass z.B. 0 und 0 eine komplexe Zahl darstellt, wobei der erste 0er der Real- und der zweite der Imaginärteil ist. Diese komplexe Zahl soll dann mit einer anderen, z.B. 1.23 0, addiert/subtrahiert/whatever werden. --> Also brauche ich im Endeffekt 2 structs und jedes davon bekommt 2 Variablen. --> 2 Zeiger, jeder zeigt auf ein struct ... 

^^ Habe ich die Angabe jetzt endlich gecheckt, oder nur auf eine ganz neue Art falsch interpretiert?  

Wenn meine Annahme hier stimmt, müsste jedenfalls sowas in die Richtung hinkommen:

```
int main(void) {
    komplex_t *k1, *k2;
    komplex_t komplex_1 = { 1.23, 0 };
    komplex_t komplex_2 = { 0, 0 };
    k1=&komplex_1;
    k2=&komplex_2;

    print_komplex(k1);

    return 0;
}
```


----------



## bingo88 (28. November 2012)

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

Aber so greift man doch net auf structs zu  Dafür gibt es den Punkt- bzw. Pfeil-Operator.


```
/* normale Variable (kein Zeiger) */
komplex_t k1;

k1.a = 1.0f;
k1.b = 0.0f;

/* Zeiger auf k1 */
komplex_t k2 = &k1;
k2->a = 2.0f;
k2->b = 1.0f;

/* k1 enthält jetzt a = 2.0f und b = 1.0f */
printf("a = %f, b = %f\n", k1.a, k1.b);
printf("a = %f, b = %f\n", k2->a, k2->b);
```
Zum Thema Zeiger: Ein Zeiger zeigt auf einen Speicherbereich, genauer gesagt meist auf dessen Startadresse. Dein komplex struct besteht aus zwei Feldern, die irgendwo im Speicher liegen. In aktuellen Fall ist es (wahrscheinlich!) sogar so, dass die beiden Felder a und b direkt hintereinander liegen (kommt später). Ein Zeiger komplex_t *k zeigt also auf den Beginn deines structs (erstes byte von a), und wenn die Felder alle direkt hintereinander liegen, kann man den Zeiger auch wie ein array abarbeiten, um an die einzelnen Elemente zu kommem. Schön ist das nicht, aber es funktioniert unter Umständen (siehe dein printf mit *k).

Kommen wir nun zu dem möglichen Problem. Wie ich sagte, müssen die Felder nicht zusammenliegen. Das kommt daher, dass der Compiler - sofern man es ihm nicht verbietet - die Felder im struct so anordnet, dass sie für die CPU "günstig" liegen. Dazu fügt er ggf. sogenannte padding bytes zwischen den einzelnen Feldern ein, dein struct wird also größer. Das hat den Hintergrund, dass die CPU bestimmte Speicheradressen sehr schnell ansprechen kann (bspw. vielfaches von 4 Byte, also alles was durch 4 glatt teilbar ist). Was nicht auf dieser Byte boundary liegt, dauert viel länger. Es soll sogar Architekturen gegeben haben (oder noch geben), bei denen das genau so funktionieren MUSS. Wenn dann eine Adresse angefordert wird, die nicht auf einer byte boundary liegt, semmelt dir das Program einfach ab!

Das ist auch der Grund, warum man unbehandelte structs nicht einfach so mittels "full write" z. B. in eine Datei schreiben sollte:

```
struct MyStruct bla;
/* so nicht */
fwrite(&bla, sizeof(bla), ...);

/* sondern jedes Feld einzeln oder padding explizit abstellen */
```
So werden nämlich die ganzen padding bytes, falls welche vorhanden sind, mit in die Datei geschrieben! Und wenn die Datei dann mit einem anderen Programm (anderer Compiler / Einstellungen) gelesen werden soll, knallt es wenn du Pech hast. Wenn dein Programm nur auf einem System laufen soll, kannst du es zwar so machen, aber besonders schön ist das nicht.

Edit:
Wenn du einen Zeiger übergeben musst, kannst du dir das zusätzliche definieren einer Zeigervariable sparen.

```
komplex_t k1;

/* Adress-Operator & liefert einen Zeiger */
print_komplex(&k1);
```


----------



## DarkMo (29. November 2012)

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



boss3D schrieb:


> Ich glaube jetzt auch, verstanden zu haben, warum die Rechenfunktionen 2 Zeiger brauchen, mit denen ich ja auf insg. 4 Elemente zugreifen kann: Ich habe nämlich ursprünglich angenommen, dass 0 und 0, oder 1.23 und 0 usw. bereits jeweils ein Zahlenpaar ist, mit dem ich rechnen soll. Es dürfte aber vielmehr so sein, dass z.B. 0 und 0 eine komplexe Zahl darstellt, wobei der erste 0er der Real- und der zweite der Imaginärteil ist. Diese komplexe Zahl soll dann mit einer anderen, z.B. 1.23 0, addiert/subtrahiert/whatever werden. --> Also brauche ich im Endeffekt 2 structs und jedes davon bekommt 2 Variablen. --> 2 Zeiger, jeder zeigt auf ein struct ...


 es scheint ja schon am grundlegenden gescheitert zu sein  kennst du vektoren? ein 2D vektor V, der an der position 2|3 im kooridnatensystem steht, hat also die teile x=2 und y=3. der ganze vektor beinhaltet aber eben beide teile.


```
struct myVector {
     double x;
     double y;
}

myVector addVectors(myVector a, myVectorB b) {
      myVector c;
      c.x = a.x + b.x;
      c.y = a.y + b.y;
     return c;
}

double distance(myVector a, myVectorB b) {
      myVector c = addVectors(a, b);
      return sqrt(c.x * c.x + c.y * c.y); // die wurzel der summe der quadrierten einzelteile
}

void main(void) {
      myVector A;
      A.x = 2;
      A.y = 3;
      myVector B;
      A.x = 5;
      A.y = -1;

      printf("distance: %6.2f", distance(A, B));
}
```
eine normale int variable kann nur eine zahl speichern, für nen vektor brauch man aber eben 2 (oder mehr) variablen, die irgendwie zusammen gehören. dafür gibts structs. da hast du deine ganzen variablen unter einem dach. ein zeiger auf ne struct zeigt dann eben auf das ganze paket. über den zeiger kannste dann wieder auf die einzelteile des pakets zugreifen. oben hab ich mal paar simple rechnungen mit vektoren gebastelt. wie sich das nu im detail bei komplexen zahlen verhält, weis ich jetz auch ned, aber bingo hat ja scho mit links um sich geworfen ^^ damit sollte es eigentlich sehr einfach sein, das ganze dann umzusetzen. variablen vom typ deiner struct erstellen, als zeiger übergeben (& greift auf die adresse einer variablen zu, ergo das, was ein zeiger erwartet) und in den funktionen einfach damit arbeiten (-> operator bla. wurde ja schon schön erklärt ^^). das schlimmste sin dann ggf die rechenoperationen, aber dazu haste ja auch scho nen link erhalten


----------



## boss3D (29. November 2012)

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

^^ Danke für alle Tipps! 

Habe jetzt mal die Ausgabefunktion entsprechend der Angabe gestaltet (das mit den Vorzeichen und Blanks fehlt noch, ich weiß) und die ersten 3 Rechenfunktionen gebastelt:

```
#include <stdio.h>

typedef struct {
    double real;
    double imaginary;
} komplex_t;

void print_komplex(komplex_t *k) {
    if (k->real==0 && k->imaginary!=0) {
        printf("( %.2lfi )\n", k->imaginary);
    } else if (k->imaginary==0 && k->real!=0) {
        printf("( %.2lf )\n", k->real);
    } else if (k->real==0 && k->imaginary==0) {
        printf("( %.0lf )\n", 0);
    } else if (k->real!=0 && k->imaginary!=0) {
        printf("( %.2lf %.2lfi )\n", k->real, k->imaginary);
    }
}

komplex_t add_k(komplex_t *k1, komplex_t *k2) {
    komplex_t *k3;
    komplex_t result = { 0, 0 };
    k3=&result;

    k3->real=k1->real+k2->real;
    k3->imaginary=k1->imaginary+k2->imaginary;

    return *k3;
}

komplex_t sub_k(komplex_t *k1, komplex_t *k2) {
    komplex_t *k3;
    komplex_t result = { 0, 0 };
    k3=&result;

    k3->real=k1->real-k2->real;
    k3->imaginary=k1->imaginary-k2->imaginary;

    return *k3;
}

komplex_t mul_k(komplex_t *k1, komplex_t *k2) {
    komplex_t *k3;
    komplex_t result = { 0, 0 };
    k3=&result;

    k3->real=k1->real*k2->real-k1->imaginary*k2->imaginary;
    k3->imaginary=k1->real*k2->imaginary+k1->imaginary*k2->real;

    return *k3;
}

komplex_t div_k(komplex_t *k1, komplex_t *k2) {

}

int main(void) {
    komplex_t *k1, *k2, *k3;
    komplex_t komplex_1 = { 1.23, 0 };
    komplex_t komplex_2 = { 0, 0 };
    komplex_t result = { 0, 0 };
    k1=&komplex_1;
    k2=&komplex_2;
    k3=&result;
    
    *k3=add_k(k1, k2);
    print_komplex(k3);
    
    *k3=sub_k(k1, k2);
    print_komplex(k3);

    *k3=mul_k(k1, k2);
    print_komplex(k3);

    return 0;
}
```
Funktioniert auch bereits, allerdings sieht man es in dem Fall nicht wirklich, weil z.B. 1.23 + 0 ja wieder 1.23 ergibt (ergo, Ausgabe bleibt gleich). Wenn man aber testweise in der main für den Realteil von komplex_2 3 einsetzt, wird wirklich 4.23 ausgegeben. 

Jetzt geht's an die Multiplikation ...

^^ Wenn das dann auch noch erledigt ist, muss ich mir nur noch was Schlaues überlegen, damit bei vollständigen komplexen Zahlen zwischen den Zahlen und ihren zugehörigen Rechenzeichen jeweils ein Leerzeichen ist. Siehe:


> Eine vollständige komplexe Zahl (weder Real- noch Imaginärteil sind 0) sollte wie folgt ausgegeben
> werden: ( - 5.34 + 2.30i ) oder ( 2.34 + 1.00i )


*[EDIT]*
Hätte den Code jetzt soweit fertig, dass die Berechnungen alle ordentlich funktionieren. Habe zum Testen auch brauchbare Zahlen eingesetzt:


Spoiler





```
#include <stdio.h>

typedef struct {
    double real;
    double imaginary;
} komplex_t;

void print_komplex(komplex_t *k) {
    if (k->real==0 && k->imaginary!=0) {
        printf("( %.2lfi )\n", k->imaginary);
    } else if (k->imaginary==0 && k->real!=0) {
        printf("( %.2lf )\n", k->real);
    } else if (k->real==0 && k->imaginary==0) {
        printf("( %.0lf )\n", 0);
    } else if (k->real!=0 && k->imaginary!=0) {
        printf("( %.2lf %.2lfi )\n", k->real, k->imaginary);
    }
}

komplex_t add_k(komplex_t *k1, komplex_t *k2) {
    komplex_t *k3;
    komplex_t result = { 0, 0 };
    k3=&result;

    k3->real=k1->real+k2->real;
    k3->imaginary=k1->imaginary+k2->imaginary;

    return *k3;
}

komplex_t sub_k(komplex_t *k1, komplex_t *k2) {
    komplex_t *k3;
    komplex_t result = { 0, 0 };
    k3=&result;

    k3->real=k1->real-k2->real;
    k3->imaginary=k1->imaginary-k2->imaginary;

    return *k3;
}

komplex_t mul_k(komplex_t *k1, komplex_t *k2) {
    komplex_t *k3;
    komplex_t result = { 0, 0 };
    k3=&result;

    k3->real=k1->real*k2->real-k1->imaginary*k2->imaginary;
    k3->imaginary=k1->real*k2->imaginary+k1->imaginary*k2->real;

    return *k3;
}

komplex_t div_k(komplex_t *k1, komplex_t *k2) {
    komplex_t *k3;
    komplex_t result = { 0, 0 };
    k3=&result;

    k3->real=((k1->real*k2->real+k1->imaginary*k2->imaginary)/(k2->real*k2->real+k2->imaginary*k2->imaginary));
    k3->imaginary=((k1->imaginary*k2->real-k1->real*k2->imaginary)/(k2->real*k2->real+k2->imaginary*k2->imaginary));

    return *k3;
}

int main(void) {
    komplex_t *k1, *k2, *k3;
    komplex_t komplex_1 = { 1.23, 2 };
    komplex_t komplex_2 = { 1, 3.1 };
    komplex_t result = { 0, 0 };
    k1=&komplex_1;
    k2=&komplex_2;
    k3=&result;
    
    *k3=add_k(k1, k2);
    print_komplex(k3);
    
    *k3=sub_k(k1, k2);
    print_komplex(k3);

    *k3=mul_k(k1, k2);
    print_komplex(k3);

    *k3=div_k(k1, k2);
    print_komplex(k3);

    return 0;
}
```



Jetzt halt noch das mit den Leerzeichen ...


----------



## boss3D (29. November 2012)

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

So, die Ausgabe entspricht jetzt den Vorgaben, nur ob's der Code auch tut?!   --> Siehe void print ...
^^ Erfüllt mein Ansatz die Vorgaben, oder hätte das ...


> (achte auch auf die konkrete Verwendung von Blanks!)


... anders realisiert werden müssen?

```
#include <stdio.h>

typedef struct {
    float real;
    float imaginary;
} komplex_t;

void print_komplex(komplex_t *k) {
    if (k->real==0 && k->imaginary!=0) {
        printf("( %.2fi )\n", k->imaginary);
    } else if (k->imaginary==0 && k->real!=0) {
        printf("( %.2f )\n", k->real);
    } else if (k->real==0 && k->imaginary==0) {
        printf("( %.0f )\n", 0);
    } else if (k->real!=0 && k->imaginary!=0) {
       [COLOR=royalblue][B] if (k->real>0 && k->imaginary>0) {[/B][COLOR=seagreen] /* + + */[B]
            printf("( %.2f + %.2fi )\n", k->real, k->imaginary);
        } else if (k->real<0 && k->imaginary<0) { [/B][COLOR=seagreen]/* - - */
           [COLOR=royalblue][B] k->real*=-1;[/B][B]
            k->imaginary*=-1;
            printf("( - %.2f - %.2fi )\n", k->real, k->imaginary); 
        } else if (k->real<0 && k->imaginary>0) { [/B][COLOR=seagreen]/* - + */[B]
            k->real*=-1;
            printf("( - %.2f + %.2fi )\n", k->real, k->imaginary);
        } else if (k->real>0 && k->imaginary<0) { [/B][COLOR=seagreen]/* + - */[B]
            k->imaginary*=-1;
            printf("( %.2f - %.2fi )\n", k->real, k->imaginary);
        }[/B]    }
}

komplex_t add_k(komplex_t *k1, komplex_t *k2) {
    komplex_t res = { k1->real+k2->real, k1->imaginary+k2->imaginary };

    return res;
}

komplex_t sub_k(komplex_t *k1, komplex_t *k2) {
    komplex_t res = { k1->real-k2->real, k1->imaginary-k2->imaginary };

    return res;
}

komplex_t mul_k(komplex_t *k1, komplex_t *k2) {    
    komplex_t res = { k1->real*k2->real-k1->imaginary*k2->imaginary, k1->real*k2->imaginary+k1->imaginary*k2->real };

    return res;
}
komplex_t div_k(komplex_t *k1, komplex_t *k2) {
    komplex_t res = { (k1->real*k2->real+k1->imaginary*k2->imaginary)/(k2->real*k2->real+k2->imaginary*k2->imaginary), 
                      (k1->imaginary*k2->real-k1->real*k2->imaginary)/(k2->real*k2->real+k2->imaginary*k2->imaginary) };

    return res;
}

int main(void) {
    komplex_t *res;
    komplex_t komplex_1 = { 0, 0 };
    komplex_t komplex_2 = { 1.23, 0 };
    komplex_t komplex_3 = { 0, 3.14 };
    komplex_t komplex_4 = { -2.34, 1 };
    komplex_t komplex_5 = { -3, 4 };
    komplex_t komplex_6 = { 1, 3 };
    komplex_t komplex_7 = { 1, 1 };
    komplex_t result = { 0, 0 };
    res=&result;
    
    [COLOR=seagreen]/* Additionen */    *res=add_k(&komplex_1, &komplex_2);
    print_komplex(res);
    *res=add_k(&komplex_3, &komplex_4);
    print_komplex(res);
    
    [COLOR=seagreen]/* Subtraktionen */    *res=sub_k(&komplex_3, &komplex_4);
    print_komplex(res);
    *res=sub_k(&komplex_5, &komplex_6);
    print_komplex(res);

    [COLOR=seagreen]/* Multiplikationen */    *res=mul_k(&komplex_5, &komplex_7);
    print_komplex(res);
    *res=mul_k(&komplex_6, &komplex_7);
    print_komplex(res);

    [COLOR=seagreen]/* Divisionen */    *res=div_k(&komplex_1, &komplex_2);
    print_komplex(res);
    *res=div_k(&komplex_4, &komplex_6);
    print_komplex(res);

    return 0;
}
```
BTW: Es heißt ja auch, man soll das Programm mit allen in der Angabe angegebenen komplexen Zahlen testen. Dann hätte ich ja so eine lange ^^ main. Oder geht das auch kürzer?

Habe schon alles wegoptimiert, was mir unnötig vorkam. Geht noch mehr?


----------



## boss3D (30. November 2012)

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

^^ Die Fragen im letzten Posting bezgl. der korrekten Umsetzung der Vorgaben aus der Angabe gelten immer noch ...

Jetzt gerade bräuchte ich aber schnell den Hinweis, warum folgendes Programm auch bei Schaltjahren sagt, dass ein Februar mit 29 Tagen ungültig ist:

```
#include <stdio.h>

int isLeapYear(short year) {
    if (year%4==0 && year%400==0 && year%100!=0) {
        return 1;
    }

    return 0;
}

int checkDate(short day, short month, short year) {
    if (day<=15 && month<=10 && year<=1582) { [COLOR=seagreen]/* Gregorianische Zeitrechnung: Datum muss nach diesem Tag sein. */        return 0;
    } else if (month<1 || month>12) { [COLOR=seagreen]/* Es gibt nur 12 Monate. */        return 0;
    } else if ((month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12) && (day<1 || day>31)) { [COLOR=seagreen]/* All diese Monate müssen zwischen 1 und 31 Tage haben. */        return 0;
    } else if ((month==4 || month==6 || month==9 || month==11) && (day<1 || day>30)) { [COLOR=seagreen]/* All diese Monate müssen zwischen 1 und 30 Tage haben. */        return 0;
    } [COLOR=royalblue][B]else if (month==2 && isLeapYear(year)==0 && (day<1 || day>28)) { [/B][COLOR=seagreen]/* Ein Februar in einem Nicht-Schaltjahr muss zwischen 1 und 28 Tage haben. */[B]
        return 0;
    } else if (month==2 && isLeapYear(year)==1 && (day<1 || day>29)) { [/B][COLOR=seagreen]/* Ein Februar in einem Schaltjahr muss zwischen 1 und 29 Tage haben. */[B]
        return 0;
    }[/B]
    return 1;
}

int main(void) {
    short day=0, month=0, year=0;

    printf("Please enter a day, a month and a year: ");
    scanf("%hu %hu %hu", &day, &month, &year); 
    if (checkDate(day, month, year)==1) {
        printf("The date you entered is valid.\n");
    } else {
        printf("You entered an invalid date!\n");
    }

    return 0;
}
```
Ich bin schon seit 2 Stunden am Durchprobieren aller möglichen else-if Varianten und &&- bzw. ||-Verknüpfungen, aber ich komme einfach nicht drauf. Es läuft immer darauf hinaus, dass eben ein Schaltjahr-Februar mit 29 Tagen ungültig ist, oder jeder Februar mit x-beliebig vielen Tagen gütlig ist. Bei mir im Kopf dreht sich schon alles. Höchstwahrscheinlich handelt es sich eh nur um was Banales, aber ich seh's einfach nicht ...

*[EDIT]*
Hab's schon rausgefunden. Der Fehler lag nicht, wie zuerst vermutet, in den else-if in der Funktion _checkDate()_, sondern in _isLeapYear()_. So funktioniert's:

```
int isLeapYear(short year) {
    if [COLOR=royalblue][B]((year%4==0 && year%100!=0) || (year%100!=0 && year%400==0))[/B] {
        return 1;
    }

    return 0;
}
```
Wer Zeit und Lust hat, dem wäre ich sehr dankbar, wenn wir noch klären könnten, ob ich das mit den Leerzeichen im Komplexe-Zahlen-Beispiel richtig gemacht habe.


----------



## boss3D (6. Dezember 2012)

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

Habe jetzt mal aus Interesse probiert, das Lauflängencodierungs-Programm so umzuschreiben, dass es für beliebig viele gleiche Buchstaben hintereinander funktioniert. 

*[EDIT]*
Okay, die Längenermittlung habe ich jetzt in eine eigene Funktion gepackt. Somit kann ich Zahlen verdrehen so viel ich will und die Länge wird trotzdem richtig ermittelt, wenn nur der Funktionsaufruf an der richtigen Stelle erfolgt (was er bei mir ja jetzt tut). 

Jetzt müsste ich es nur noch schaffen, den 16er und den 12er zu verdrehen, dann könnte ich endlich decodieren. Kann mir da bitte jemand verraten, warum mir nur der 104er verdreht wird, aber dann keine Zahlen >9 mehr (siehe blau markierte Schleife)?

```
#include <stdio.h>
#include <math.h>

[COLOR=seagreen]/* Längenermittlung für Strings. */int checkLength(char *s) {
    int i=0, j=0, k=0, count1=0, count2=0, length=0;

    while (*(s+i)!='\0') {
        if (*(s+i+1)>=48 && *(s+i+1)<=57) {[COLOR=seagreen] /* Solange Zahlen gefunden werden, ... */            count1++;[COLOR=seagreen] /* ... erhöhe Zähler. */            for (j=count1, k=(j-1); j>=0; j--, k--) {
                count2+=(k*(int)pow(10., j)); [COLOR=seagreen]/* Berechne Gesamtzahl als integer und ... */            }
            i+=count2;
            length+=count2; [COLOR=seagreen]/* ... addiere sie zu length. Sonst, ... */        } else {
            i++;
            length++; [COLOR=seagreen]/* ... zähle nur 1 dazu für jeweils einen Buchstaben. */        }
    }

    return length;
}

[COLOR=seagreen]/* 
Funktion calc nötig, um Zahlenstellen in der richtigen Reihenfolge ausgeben lassen zu können 
durch verkleinern der entsprechenden Indexe von *s anhand des Rückgabewertes. 
*/int calcSteps(int num) {
    int temp1=num, temp2=0, count=0;

    while (temp1>0) {
        temp2=temp1%10;
        temp1/=10;
        count++; [COLOR=seagreen]/* Ermittle Anzahl der nötigen Rechenschritte und somit auch die Anzahl der Stellen der Zahl. */    }

    return count;
}

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

    [COLOR=seagreen]/* Codieren des Original-Strings: */    while (*(s+i) != '\0') {
        if (*(s+i)!=*(s+j)) { [COLOR=seagreen]/* Sobald Buchstabe nicht mehr gleich seinem Nachfolger ist, prüfe: */            if ((j-count1)==1) { [COLOR=seagreen]/* Einmaliges Vorkommen? */                *(s+k)=*(s+i);[COLOR=seagreen] /* Überschreibe Feld von vorne beginnend mit Buchstaben ... */                k++; [COLOR=seagreen]/* ... und springe im Index um 1 weiter. */                count1=j;
            } else {[COLOR=seagreen] /* Mehrmaliges Vorkommen? */                *(s+k)=*(s+i); [COLOR=seagreen]/* Überschreibe Feld von vorne beginnend mit Buchstaben. */                if ((j-count1)>9) { [COLOR=seagreen]/* Vorkommen größer als 9: */                    temp1=(j-count1);
                    while (temp1>0) { [COLOR=seagreen]/* Zerlege (An)Zahl in ihre einzelnen Stellen. */                        temp2=temp1%10;
                        temp1/=10;
                        count2++; [COLOR=seagreen]/* Zähle Rechenschritte mit um Anzahl der nötigen Stellen und somit Indexe zu ermitteln. */                        *(s+k+(calcSteps(temp1)+1))=(char)(temp2+48);[COLOR=seagreen] /* Überschreibe entsprechend viele Feldelemente mit den Stellen der Vorkommenszahl. */                    }
                    k+=count2; [COLOR=seagreen]/* Dann springe entsprechend viele Indexe weiter, um an die nächste zu überschreibende Stelle zu gelangen. */                    count1=j;
                    count2=1;
                } else {[COLOR=seagreen] /* Vorkommen bis 9: */                    *(s+k+1)=(char)((j-count1)+48);
                    k+=2;[COLOR=seagreen] /* Ein Buchstabe und seine Zahl wurden geschrieben. Springe daher 2 Indexe weiter. */                    count1=j;
                }
            }            
        }
        i++;
        j++;
    }
    ratio=(double)k; [COLOR=seagreen]/* ratio enthält am Ende der Schleife die Länge der Codierung. */    *(s+(int)ratio)='\0'; [COLOR=seagreen]/* Hänge an die Codierung noch eine Nullterminierung an. */
    printf("%s", s); [COLOR=seagreen]/* Ausgabe: Codierter String */
    return ((ratio*100)/(double)length);
}

int decode_runlength(char *s) {
    int i=0, j=0, k=0, temp1=0, temp2=0, count1=0, count2=0, length=checkLength(s);

    [COLOR=seagreen]/* Verdrehen der Zahlen >9, da String später von hinten beginnend ausgewertet wird: */  [COLOR=royalblue][B]  while (*(s+i)!='\0') {
        if (*(s+i+1)>=48 && *(s+i+1)<=57) { 
            j++;
            count1=(*(s+i+1)-48); 
            count2+=(count1*(int)pow(10., j-1)); [/B][COLOR=seagreen]/* Berechne Gesamtzahl als integer und ... */[B]
            if ((count2/10)>0) {
                temp1=count2;
            }
            while (temp1>0) { [/B][COLOR=seagreen]/* Zerlege int-Zahl in ihre einzelnen Stellen. */[B]
                temp2=temp1%10;
                temp1/=10;
                *(s+i+(calcSteps(temp1))-1)=(char)(temp2+48); [/B][COLOR=seagreen]/* Überschreibe entsprechend viele Feldelemente mit den Stellen der Vorkommenszahl. */[B]
            }
            i+=count2;
        } else {
            i++;
        }
    }[/B]
    [COLOR=seagreen]/* Decodiere String: */
    printf("%s", s); [COLOR=seagreen]/* Ausgabe: Decodierter String */
    return 0;
}

int main(void) {
[COLOR=seagreen]//int main(int argc, char *argv[]) {    [COLOR=seagreen]//char *s = argv[1];    char s[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBCCCCCCCCCCCCCCCCDEABBBBDDDDDDDDDDDD";
    int i=0;

    /* Kleinbuchstaben in Großbuchstaben umwandeln */
    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;
}
```
^^ Ich vermute, dass es irgendwie mit dem i+=count2 zusammenhängt. count2 wird ja eine so große Zahl, die weit über der Nullterminierung liegen würde und somit hört die Schleife einfach auf. Für meine Logik müsste ja i+=j, oder von mir aus auch i+=(j+1) hinkommen, aber beide Versionen liefern nur Blödsinn und überschreiben meine Buchstaben ...  

j zählt jedenfalls, wie viele Ziffern hintereinander stehen bevor wieder ein Buchstabe kommt, und genau so weit müsste ich doch im codierten String weiterspringen?!


----------



## boss3D (7. Dezember 2012)

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

^^ Keiner eine Idee?

*[EDIT]*
Man staune, aber es ist wahr: Die ganze Invertiererei ist völlig für'n A****, weil durch das Berechnen der int-Gesamtzahl automatisch immer die Stellen verdreht werden! Und um das rauszufinden, habe ich 6 h gebraucht.  

Bsp: Der Compiler kommt von hinten an die Werte heran und liest --> 2 1, bevor er auf einen Buchstaben trifft. Jetzt sollte man meinen, dass die beiden chars 2 und 1 in einen int-21er umgerechnet werden, den ich dann drehen müsste, um meinen 12er zu erhalten. Aber nein! Die beiden chars werden bereits beim Umrechnen verdreht und raus kommt mein int-12er. 

Tja, jetzt brauche ich also nur die Decodier-Funktion neu zu schreiben. Bin auch schon dabei, aber ein Bisschen hapert es noch. Mal neu überlegen, das Ganze. Tipps auf jeden Fall erwünscht! 


Spoiler





```
#include <stdio.h>
#include <math.h>

[COLOR=seagreen]/* Längenermittlung für Strings. */int checkLength(char *s) {
    int i=0, j=0, k=0, count1=0, count2=0, length=0;

    while (*(s+i)!='\0') {
        if (*(s+i+1)>=48 && *(s+i+1)<=57) { [COLOR=seagreen]/* Solange Zahlen gefunden werden, ... */            count1++;[COLOR=seagreen] /* ... erhöhe Zähler. */            for (j=count1, k=(j-1); j>=0; j--, k--) {
                count2+=(k*(int)pow(10., j)); [COLOR=seagreen]/* Berechne Gesamtzahl als integer und ... */            }
            i+=count2;
            length+=count2; [COLOR=seagreen]/* ... addiere sie zu length. Sonst, ... */        } else {
            i++;
            length++; [COLOR=seagreen]/* ... zähle nur 1 dazu für jeweils einen Buchstaben. */        }
    }

    return length;
}

[COLOR=seagreen]/* 
Funktion calc nötig, um Zahlenstellen in der richtigen Reihenfolge ausgeben lassen zu können 
durch verkleinern der entsprechenden Indexe von *s anhand des Rückgabewertes. 
*/int calcSteps(int num) {
    int temp1=num, temp2=0, count=0;

    while (temp1>0) {
        temp2=temp1%10;
        temp1/=10;
        count++; [COLOR=seagreen]/* Ermittle Anzahl der nötigen Rechenschritte und somit auch die Anzahl der Stellen der Zahl. */    }

    return count;
}

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

   [COLOR=seagreen] /* Codieren des Original-Strings: */    while (*(s+i) != '\0') {
        if (*(s+i)!=*(s+j)) { [COLOR=seagreen]/* Sobald Buchstabe nicht mehr gleich seinem Nachfolger ist, prüfe: */            if ((j-count1)==1) { [COLOR=seagreen]/* Einmaliges Vorkommen? */                *(s+k)=*(s+i); [COLOR=seagreen]/* Überschreibe Feld von vorne beginnend mit Buchstaben ... */                k++; [COLOR=seagreen]/* ... und springe im Index um 1 weiter. */                count1=j;
            } else { [COLOR=seagreen]/* Mehrmaliges Vorkommen? */                *(s+k)=*(s+i); [COLOR=seagreen]/* Überschreibe Feld von vorne beginnend mit Buchstaben. */                if ((j-count1)>9) {[COLOR=seagreen] /* Vorkommen größer als 9: */                    temp1=(j-count1);
                    while (temp1>0) { [COLOR=seagreen]/* Zerlege (An)Zahl in ihre einzelnen Stellen. */                        temp2=temp1%10;
                        temp1/=10;
                        count2++; [COLOR=seagreen]/* Zähle Rechenschritte mit um Anzahl der nötigen Stellen und somit Indexe zu ermitteln. */                        *(s+k+(calcSteps(temp1)+1))=(char)(temp2+48); [COLOR=seagreen]/* Überschreibe entsprechend viele Feldelemente mit den Stellen der Vorkommenszahl. */                    }
                    k+=count2; [COLOR=seagreen]/* Dann springe entsprechend viele Indexe weiter, um an die nächste zu überschreibende Stelle zu gelangen. */                    count1=j;
                    count2=1;
                } else {[COLOR=seagreen] /* Vorkommen bis 9: */                    *(s+k+1)=(char)((j-count1)+48);
                    k+=2; [COLOR=seagreen]/* Ein Buchstabe und seine Zahl wurden geschrieben. Springe daher 2 Indexe weiter. */                    count1=j;
                }
            }            
        }
        i++;
        j++;
    }
    ratio=(double)k;[COLOR=seagreen] /* ratio enthält am Ende der Schleife die Länge der Codierung. */    *(s+(int)ratio)='\0'; [COLOR=seagreen]/* Hänge an die Codierung noch eine Nullterminierung an. */
    printf("%s", s); [COLOR=seagreen]/* Ausgabe: Codierter String */
    return ((ratio*100)/(double)length);
}

int decode_runlength(char *s) {
    int i=0, j=0, k=0, temp1=0, temp2=0, count1=0, count2=0, length1=checkLength(s), length2=0;
    
    while (*(s+length2)!='\0') {
        length2++;
    }
    
   [COLOR=seagreen] /* Decodiere String: */[COLOR=royalblue][B]
    *(s+length1)='\0'; 
    i=length1;[/B][COLOR=seagreen] /* length1 = Originallänge des Strings. */[B]
    j=length2; [/B][COLOR=seagreen]/* length2 = Länge des codierten Strings. */[B]
    while (i>0) {
        if (*(s+j)>=48 && *(s+j)<=57) { [/B][COLOR=seagreen]/* Zahl gefunden: */[B]
            k++;
            count1=(*(s+j)-48); 
            count2+=(count1*(int)pow(10., k-1)); [/B][COLOR=seagreen]/* Berechne Gesamtzahl als integer und ... */[B]
            temp1=count2;
            if ((temp1/10)>0) {
                while (temp1>0) { [/B][COLOR=seagreen]/* ... gib überschreibe Feld von hinten beginnend gemäß dieser Anzahl mit dem zugehörigen Buchstaben. */[B]
                    *(s+i)=*(s+j-k+1);
                    temp1--;
                }
            }
        } else if (*(s+j)>=65 && *(s+j)<=90) { [/B][COLOR=seagreen]/* Buchstabe gefunden: */[B]
            break;
        }
        i--;
        j--;
    }
[/B]    printf("%s", s); [COLOR=seagreen]/* Ausgabe: Decodierter String */
    return 0;
}

int main(void) {
[COLOR=seagreen]//int main(int argc, char *argv[]) {   [COLOR=seagreen] //char *s = argv[1];    char s[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBCCCCCCCCCCCCCCCCDEABBBBDDDDDDDDDDDD";
    int i=0;

    [COLOR=seagreen]/* Kleinbuchstaben in Großbuchstaben umwandeln */    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;
}
```



Was ich noch nicht durchschaut habe: Wieso ergibt das ...

```
[COLOR=seagreen]/* Decodiere String: */    *(s+length1)='\0'; 
    i=length1; [COLOR=seagreen]/* length1 = Originallänge des Strings. */    j=length2; [COLOR=seagreen]/* length2 = Länge des codierten Strings. */    while (i>0) {
        if (*(s+j)>=48 && *(s+j)<=57) { [COLOR=seagreen]/* Zahl gefunden: */            k++;
            count1=(*(s+j)-48); 
            count2+=(count1*(int)pow(10., k-1)); [COLOR=seagreen]/* Berechne Gesamtzahl als integer und ... */            temp1=count2;
            temp2=count2;
            if ((temp1/10)>0) {
                while (temp1>0) {[COLOR=seagreen] /* ... gib überschreibe Feld von hinten beginnend gemäß dieser Anzahl mit dem zugehörigen Buchstaben. */                    *(s+i)=*(s+j-k+1);
                    temp1--;
                }
            }
           [COLOR=royalblue][B] i-=temp2;
            j-=k;[/B]        } else if (*(s+j)>=65 && *(s+j)<=90) { [COLOR=seagreen]/* Buchstabe gefunden: */            *(s+i)=*(s+j);
          [COLOR=royalblue][B]  i--;
            j--;[/B]        }
    }
```
... keine Ausgabe? Endlosschleife? Wenn ja, warum? Liegt's an den Dekrementen? Irgendwie muss ich verringern um im Feld nach vorne zu kommen ...

Wir haben es ja früher in der Version mit Buchstaben bis 9 auch nicht anders gemacht. Bei Einmalvorkommenden nur Zähler--, weil wir ja nur um 1 Index weiter nach vorne müssen, sonst eben Zähler-=8 (zum Beispiel), wenn acht gleiche Buchstaben nebeneinander geschrieben werden mussten. Jetzt kann's halt auch schon mal Zähler-=25 oder so heißen und temp2 speichert ja nun den großen Wert?! Warum funktioniert das Nachvornespringen jetzt nicht mehr ordentlich?
*
[EDIT2]*
2 Dinge konnte ich noch rausfinden: Bei j muss es eigentlich immer j-- heißen, weil wir ja von char Ziffer zu char Ziffer weiterspringen müssen, um aus den Ziffern die int-Gesamtzahl zu berechnen. Wir haben ja nicht von Anfang an eine mehrstellige gesamte Zahl, die wir überspringen könnten um das Element davor anzuschauen.
Und ich habe mir mal testweise den Inhalt von temp1 ausgeben lassen: Man sieht, dass darin immer die aktuelle gefundene char Ziffer gespeichert wird, aber nicht der berechnete int-Gesamtwert, den ich darin haben will. Da müssen wir irgendwie ansetzen ...




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



^^ Zumindest die 2 1, die 4, die 6 1, die 3 und die 4 0 1 in temp1 machen Sinn. Daraus müssen ja die int-Gesamtzahlen 12, 16 und 104 berechnet bzw. 4 und 3 erkannt werden und das möchte ich dann in temp1 haben. Was die ganzen anderen Zahlen in temp1 sein sollen, weiß ich genausowenig, wie warum dann in char *s sowas komisches gespeichert (und bis zur '\0' ausgegeben wird). 

Obige Ausgabe erreicht mit folgendem Code:


Spoiler





```
[COLOR=seagreen]/* Decodiere String: */
   [COLOR=black] *(s+length1)='\0'; 
    i=length1;[COLOR=seagreen] /* length1 = Originallänge des Strings. */    j=length2;[COLOR=seagreen] /* length2 = Länge des codierten Strings. */    while (i>0) {
        if (*(s+j)>=48 && *(s+j)<=57) { [COLOR=seagreen]/* Zahl gefunden: */            k++;
            count1=(*(s+j)-48); 
            count2+=(count1*(int)pow(10., k-1)); [COLOR=seagreen]/* Berechne Gesamtzahl als integer und ... */            temp1=count2;
            temp2=count2;
            printf("temp1 = %d\n", temp1);
            if ((temp1/10)>0) {
                while (temp1>0) { [COLOR=seagreen]/* ... gib überschreibe Feld von hinten beginnend gemäß dieser Anzahl mit dem zugehörigen Buchstaben. */                    *(s+i)=*(s+j-k+1);
                    temp1--;
                }
            }        
            i-=temp2;
            count1=0;
            count2=0;
            k=0;
        } else if (*(s+j)>=65 && *(s+j)<=90) { [COLOR=seagreen]/* Buchstabe gefunden: */            *(s+i)=*(s+j);
            i--;
        }
        j--;
    }
```



Wie bekomme ich die int-Gesamtzahlen anstelle der char Ziffern in temp1 rein?

*[EDIT3]*
So ganz langsam sehe ich die Fehler: 
1. count2 rechnet richtig, summiert die Ergebnisse aber nicht auf.
2. Der erste 4er von hinten betrachtet fließt auch in die Rechnung ein, obwohl zwischen dem 2 1 und dem 4er ein D steht.
3. Die Schleife wird dann scheinbar verlassen und der 3er, der 16er und der 104er werden nicht mehr berechnet.




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



^^ Die 3 Fehler müssen wir beheben. Dann hätten wir's fast/ganz geschafft.


----------



## boss3D (7. Dezember 2012)

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

So, Zeit für ein neues Posting. ^^ Oben würde ich wahrscheinlich eh bald an's Zeichenlimit kommen ...

@ Topic
Das Aufsummieren in count2 habe ich auch noch hinbekommen (man beachte den 12er in count2):




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



Code für copy/paste, falls wer testen möchte:


Spoiler





```
#include <stdio.h>
#include <math.h>

[COLOR=seagreen]/* Längenermittlung für codierten String. */int checkLength(char *s) {
    int i=0, j=0, k=0, count1=0, count2=0, length=0;

    while (*(s+i)!='\0') {
        if (*(s+i+1)>=48 && *(s+i+1)<=57) { [COLOR=seagreen]/* Solange Zahlen gefunden werden, ... */            count1++; [COLOR=seagreen]/* ... erhöhe Zähler. */            for (j=count1, k=(j-1); j>=0; j--, k--) {
                count2+=(k*(int)pow(10., j)); [COLOR=seagreen]/* Berechne Gesamtzahl als integer und ... */            }
            i+=count2;
            length+=count2; [COLOR=seagreen]/* ... addiere sie zu length. Sonst, ... */        } else {
            i++;
            length++; [COLOR=seagreen]/* ... zähle nur 1 dazu für jeweils einen Buchstaben. */        }
    }

    return length;
}

[COLOR=seagreen]/* 
Funktion calc nötig, um Zahlenstellen in der richtigen Reihenfolge ausgeben lassen zu können 
durch verkleinern der entsprechenden Indexe von *s anhand des Rückgabewertes. 
*/int calcSteps(int num) {
    int temp1=num, temp2=0, count=0;

    while (temp1>0) {
        temp2=temp1%10;
        temp1/=10;
        count++;[COLOR=seagreen] /* Ermittle Anzahl der nötigen Rechenschritte und somit auch die Anzahl der Stellen der Zahl bzw. nötigen Indexe im Feld. */    }

    return count;
}

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

   [COLOR=seagreen] /* Codieren des Original-Strings: */    while (*(s+i) != '\0') {
        if (*(s+i)!=*(s+j)) { [COLOR=seagreen]/* Sobald Buchstabe nicht mehr gleich seinem Nachfolger ist, prüfe: */            if ((j-count1)==1) { [COLOR=seagreen]/* Einmaliges Vorkommen? */                *(s+k)=*(s+i); [COLOR=seagreen]/* Überschreibe Feld von vorne beginnend mit Buchstaben ... */                k++; [COLOR=seagreen]/* ... und springe im Index um 1 weiter. */                count1=j;
            } else { [COLOR=seagreen]/* Mehrmaliges Vorkommen? */                *(s+k)=*(s+i); [COLOR=seagreen]/* Überschreibe Feld von vorne beginnend mit Buchstaben. */                if ((j-count1)>9) { [COLOR=seagreen]/* Vorkommen größer als 9: */                    temp1=(j-count1);
                    while (temp1>0) {[COLOR=seagreen] /* Zerlege (An)Zahl in ihre einzelnen Stellen. */                        temp2=temp1%10;
                        temp1/=10;
                        count2++;[COLOR=seagreen] /* Zähle Rechenschritte mit um Anzahl der nötigen Stellen und somit Indexe zu ermitteln. */                        *(s+k+(calcSteps(temp1)+1))=(char)(temp2+48); [COLOR=seagreen]/* Überschreibe entsprechend viele Feldelemente mit den Stellen der Vorkommenszahl. */                    }
                    k+=count2; [COLOR=seagreen]/* Dann springe entsprechend viele Indexe weiter, um an die nächste zu überschreibende Stelle zu gelangen. */                    count1=j;
                    count2=1;
                } else { [COLOR=seagreen]/* Vorkommen bis 9: */                    *(s+k+1)=(char)((j-count1)+48);
                    k+=2; [COLOR=seagreen]/* Ein Buchstabe und seine Zahl wurden geschrieben. Springe daher 2 Indexe weiter. */                    count1=j;
                }
            }            
        }
        i++;
        j++;
    }
    ratio=(double)k; [COLOR=seagreen]/* ratio enthält am Ende der Schleife die Länge der Codierung. */    *(s+(int)ratio)='\0'; [COLOR=seagreen]/* Hänge an die Codierung noch eine Nullterminierung an. */
    printf("%s", s); [COLOR=seagreen]/* Ausgabe: Codierter String */
    return ((ratio*100)/(double)length);
}

int decode_runlength(char *s) {
    int i=0, j=0, k=0, temp1=0, temp2=0, count1=0, count2=0, length1=checkLength(s), length2=0;
    
    while (*(s+length2)!='\0') {
        length2++;
    }
    
    [COLOR=seagreen]/* Decodiere String: */    [COLOR=royalblue][B]*(s+length1)='\0'; 
    i=length1; [/B][COLOR=seagreen]/* length1 = Originallänge des Strings. */[B]
    j=length2;[/B][COLOR=seagreen] /* length2 = Länge des codierten Strings. */[B]
    while (i>0) {
        if (*(s+j)>=48 && *(s+j)<=57) { [/B][COLOR=seagreen]/* Zahl gefunden: */[B]
            k++;
            count1=(*(s+j)-48); 
            count2+=(count1*(int)pow(10., k-1)); [/B][COLOR=seagreen]/* Berechne Gesamtzahl als integer und ... */[B]
            printf("count2: %d | k: %d\n", count2, k);
            temp1=count2;
            temp2=count2;
            while (temp1>0) { [/B][COLOR=seagreen]/* ... überschreibe Feld von hinten beginnend gemäß dieser Anzahl mit dem zugehörigen Buchstaben. */[B]
                *(s+i)=*(s+j-calcSteps(temp2)+1);
                temp1--;
            }        
            i-=temp2;
        } else if (*(s+j)>=65 && *(s+j)<=90) { [/B][COLOR=seagreen]/* Buchstabe gefunden: */[B]
            *(s+i)=*(s+j);
            i--;
        }
        j--;
    }[/B]
    printf("%s", s); [COLOR=seagreen]/* Ausgabe: Decodierter String */
    return 0;
}

int main(void) {
[COLOR=seagreen]//int main(int argc, char *argv[]) {  [COLOR=seagreen]  //char *s = argv[1];    char s[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBCCCCCCCCCCCCCCCCDEABBBBDDDDDDDDDDDD";
    int i=0;

    [COLOR=seagreen]/* Kleinbuchstaben in Großbuchstaben umwandeln */    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;
}
```



Bleibt nur noch zu klären, warum er den 4er in die Berechnung mit dazu nimmt, obwohl zwischen 2 1 und 4 ja wie gesagt ein D steht, und zwischen Zahlen und Buchstaben sollte mein Code unterscheiden können. Habe ja die jeweiligen ASCII-Bereiche in den beiden ifs angegeben. Und dann eben noch, warum er nur den 12er berechnet und nicht alle Zahlen im codierten String. Dann hätten wir's. 

Bitte helft noch schnell! Sitze seit 3 Tagen und 2 Nächten dran und würde das wirklich sehr gerne noch heute fertig bringen. 

*[EDIT]*
Hab's geschafft, dass er jetzt immer die richtigen Werte in count2 hat und danach zu rechen aufhört, bis er wieder mit einer Zahl neu beginnt. Also 12, 4, 16, 3, 104 und die ersten Rechenschritte bei mehrstelligen Zahlen. Sobald die Schleife auf einen Buchstaben trifft, muss man die Speichervariablen für die Zahlen auf 0 setzen, damit die eben auf 0 sind, sobald wieder eine Zahl berechnet werden muss. Klingt jetzt vielleicht seltsam, ist aber total logisch, wenn man sich's im Debugger anschaut. 




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



```
[COLOR=seagreen]/* Decodiere String: */    *(s+length1)='\0'; 
    i=length1; [COLOR=seagreen]/* length1 = Originallänge des Strings. */    j=length2; [COLOR=seagreen]/* length2 = Länge des codierten Strings. */    while (i>0) {
        if (*(s+j)>=48 && *(s+j)<=57) { [COLOR=seagreen]/* Zahl gefunden: */            k++;
            count1=(*(s+j)-48); 
            count2+=(count1*(int)pow(10., k-1)); [COLOR=seagreen]/* Berechne Gesamtzahl als integer und ... */            printf("count2: %d | k: %d\n", count2, k);
            temp1=count2;
            temp2=count2;
            while (temp1>0) { [COLOR=seagreen]/* ... überschreibe Feld von hinten beginnend gemäß dieser Anzahl mit dem zugehörigen Buchstaben. */                *(s+i)=*(s+j-calcSteps(temp2)+1);
                temp1--;
            }        
            i-=temp2;
        } else if (*(s+j)>=65 && *(s+j)<=90) { [COLOR=seagreen]/* Buchstabe gefunden: */            *(s+i)=*(s+j);
            i--;
           [COLOR=royalblue][B] count2=0;
            k=0;[/B]        }
        j--;
    }
```
^^ Jetzt müssen wir nur noch ersten Rechenschritte (z.B. den 2er für den 12er) wegbekommen und die korrekte Ausgabe anhand der final errechneten Anzahlen (z.B. 12) hinbekommen ...

Er überschreibt mir den codierten Inhalt nämlich noch nicht mit dem Decodierten. Warum?

*[EDIT2]*
Zu einer Ausgabe käme ich auch schon, das Überschreiben funktioniert also schon (musste nur das i-- mit in die innere Schleife reinnehmen). Nur die Werte sind noch kompletter Blödsinn und der Fehler liegt höchstwahrscheinlich im blau markierten Code-Teil. Und die nicht erwünschten Rechenergebnisse habe ich auch noch nicht weg, aber jetzt komme ich der Sache wirklich schon verdammt nahe ...




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        




```
[COLOR=seagreen]/* Decodiere String: */    *(s+length1)='\0'; 
    i=length1; [COLOR=seagreen]/* length1 = Originallänge des Strings. */    j=length2;[COLOR=seagreen] /* length2 = Länge des codierten Strings. */    while (i>0) {
        if (*(s+j)>=48 && *(s+j)<=57) { [COLOR=seagreen]/* Zahl gefunden: */            k++;
            count1=(*(s+j)-48); 
            count2+=(count1*(int)pow(10., k-1)); [COLOR=seagreen]/* Berechne Gesamtzahl als integer und ... */            temp1=count2;
            temp2=count2;
            printf("temp1: %d\n", temp1);
            while (temp1>0) { [COLOR=seagreen]/* ... überschreibe Feld von hinten beginnend gemäß dieser Anzahl mit dem zugehörigen Buchstaben. */                *(s+i)=[COLOR=royalblue][B]*(s+j-calcSteps(temp2)+1)[/B];
                temp1--;
                i--;
            }        
        } else if (*(s+j)>=65 && *(s+j)<=90) { [COLOR=seagreen]/* Buchstabe gefunden: */            *(s+i)=*(s+j);
            i--;
            count2=0;
            k=0;
        }
        j--;
    }
```
Wenn ich in der blauen Zeile hinten +2 statt +1 schreibe, sieht die Ausgabe schon wirklich brauchbar aus, nur komme ich dann über ein Stringende, vermutlich das untere (geht ja von hinten/oben nach vorne/unten).




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



*[EDIT3]*
So, die Rechenschritte vor dem finalen Ergebnis konnte ich zwar nicht entfernen, aber immerhin wird dafür jetzt nur 0 in temp1 gespeichert. Das müsste das Problem auch lösen, weil er für while (0>0) nie in die Schleifen geht, oder?! Somit müssten nach meiner Logik nur mehr die finalen Rechenergebnisse in der Schleife landen.

Bezüglich Ausgabe hätte ich es jetzt so weit gebracht:




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



^^ Er gibt noch 1 A zu viel aus, alles andere stimmt bereits. Und hinten kommt er mir über die Nullterminierung, was ich insofern gar nicht verstehe, dass ich mich ja von hinten nach vorne durch's Feld ackere! Halleluja, ich werd' hier noch verrückt! 

Ah, Moment! Kann es sein, dass er mir durch das eine A zuviel hinten die von mir gesetzte '\0' überschreibt und deswegen noch ein paar seltsame Zeichen bis zur nächsten 0 im Speicher ausgibt? Jetzt bin ich gespannt, was passiert, sobald ich das mit dem A gerichtet habe ...  

*[EDIT4]*
Ok, für den einen String funktioniert's jetzt, für andere wieder nicht! Wie gibt's denn das jetzt?

Habe ich wohl beim Entfernen des 1 zuvielen A geschummelt?! Immer für die erste Buchstabenreihe (war ja ursprünglich die A-Kette) gibt er nämlich jetzt Blödsinn aus (bei anderen strings). Alles danach stimmt.




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        

 


			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        

 


			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



Sieht jemand den Fehler? Bevor ich hier noch durchdrehe ...

Hier der Code:


Spoiler





```
#include <stdio.h>
#include <math.h>

[COLOR=seagreen]/* Längenermittlung für codierten String. */int checkLength(char *s) {
    int i=0, j=0, k=0, count1=0, count2=0, length=0;

    while (*(s+i)!='\0') {
        if (*(s+i+1)>=48 && *(s+i+1)<=57) { [COLOR=seagreen]/* Solange Zahlen gefunden werden, ... */            count1++; [COLOR=seagreen]/* ... erhöhe Zähler. */            for (j=count1, k=(j-1); j>=0; j--, k--) {
                count2+=(k*(int)pow(10., j)); [COLOR=seagreen]/* Berechne Gesamtzahl als integer und ... */            }
            i+=count2;
            length+=count2; [COLOR=seagreen]/* ... addiere sie zu length. Sonst, ... */        } else {
            i++;
            length++; [COLOR=seagreen]/* ... zähle nur 1 dazu für jeweils einen Buchstaben. */        }
    }

    return length;
}

[COLOR=seagreen]/* 
Funktion calc nötig, um Zahlenstellen in der richtigen Reihenfolge ausgeben lassen zu können 
durch verkleinern der entsprechenden Indexe von *s anhand des Rückgabewertes. 
*/int calcSteps(int num) {
    int temp1=num, temp2=0, count=0;

    while (temp1>0) {
        temp2=temp1%10;
        temp1/=10;
        count++; [COLOR=seagreen]/* Ermittle Anzahl der nötigen Rechenschritte und somit auch die Anzahl der Stellen der Zahl bzw. nötigen Indexe im Feld. */    }

    return count;
}

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

    [COLOR=seagreen]/* Codieren des Original-Strings: */    while (*(s+i) != '\0') {
        if (*(s+i)!=*(s+j)) { [COLOR=seagreen]/* Sobald Buchstabe nicht mehr gleich seinem Nachfolger ist, prüfe: */            if ((j-count1)==1) { [COLOR=seagreen]/* Einmaliges Vorkommen? */                *(s+k)=*(s+i); [COLOR=seagreen]/* Überschreibe Feld von vorne beginnend mit Buchstaben ... */                k++; [COLOR=seagreen]/* ... und springe im Index um 1 weiter. */                count1=j;
            } else { [COLOR=seagreen]/* Mehrmaliges Vorkommen? */                *(s+k)=*(s+i); [COLOR=seagreen]/* Überschreibe Feld von vorne beginnend mit Buchstaben. */                if ((j-count1)>9) { [COLOR=seagreen]/* Vorkommen größer als 9: */                    temp1=(j-count1);
                    while (temp1>0) { [COLOR=seagreen]/* Zerlege (An)Zahl in ihre einzelnen Stellen. */                        temp2=temp1%10;
                        temp1/=10;
                        count2++; [COLOR=seagreen]/* Zähle Rechenschritte mit um Anzahl der nötigen Stellen und somit Indexe zu ermitteln. */                        *(s+k+(calcSteps(temp1)+1))=(char)(temp2+48); [COLOR=seagreen]/* Überschreibe entsprechend viele Feldelemente mit den Stellen der Vorkommenszahl. */                    }
                    k+=count2; [COLOR=seagreen]/* Dann springe entsprechend viele Indexe weiter, um an die nächste zu überschreibende Stelle zu gelangen. */                    count1=j;
                    count2=1;
                } else { [COLOR=seagreen]/* Vorkommen bis 9: */                    *(s+k+1)=(char)((j-count1)+48);
                    k+=2; [COLOR=seagreen]/* Ein Buchstabe und seine Zahl wurden geschrieben. Springe daher 2 Indexe weiter. */                    count1=j;
                }
            }            
        }
        i++;
        j++;
    }
    ratio=(double)k;[COLOR=seagreen] /* ratio enthält am Ende der Schleife die Länge der Codierung. */    *(s+(int)ratio)='\0'; [COLOR=seagreen]/* Hänge an die Codierung noch eine Nullterminierung an. */
    printf("%s", s); [COLOR=seagreen]/* Ausgabe: Codierter String */
    return ((ratio*100)/(double)length);
}

int decode_runlength(char *s) {
    int i=0, j=0, k=0, temp1=0, temp2=0, count1=0, count2=0, length1=checkLength(s), length2=0;
    
    while (*(s+length2)!='\0') {
        length2++;
    }
    
   [COLOR=seagreen] /* Decodiere String: */    
    i=length1; [COLOR=seagreen]/* length1 = Originallänge des Strings. */    j=length2+1; [COLOR=seagreen]/* length2+1 = Länge des codierten Strings. */    while (i>0) {
        if (*(s+j)>=48 && *(s+j)<=57) { [COLOR=seagreen]/* Zahl gefunden. */            k++;
            count1=(*(s+j)-48); 
            count2+=(count1*(int)pow(10., k-1)); [COLOR=seagreen]/* Berechne Gesamtzahl als integer und ... */            if (*(s+j-1)>=65 && *(s+j-1)<=90) {
                temp1=(count2-1);
                temp2=count2;
            }
            while (temp1>0) { [COLOR=seagreen]/* ... überschreibe Feld von hinten beginnend gemäß dieser Anzahl mit dem zugehörigen Buchstaben. */                *(s+i)=*(s+j-calcSteps(temp2)+(k-1));
                temp1--;
                i--;
            }        
        } else if (*(s+j)>=65 && *(s+j)<=90) { [COLOR=seagreen]/* Buchstabe gefunden. */            *(s+i)=*(s+j);
            i--;
            count2=0;
            k=0;
        }
        j--;
    }
    *(s+length1)='\0'; [COLOR=seagreen]/* Hänge an die Decodierung noch eine Nullterminierung an. */
    printf("%s", s); [COLOR=seagreen]/* Ausgabe: Decodierter String */
    return 0;
}

int main(void) {
[COLOR=seagreen]//int main(int argc, char *argv[]) {    [COLOR=seagreen]//char *s = argv[1];    char s[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBCCCCCCCCCCCCCCCCDEABBBBDDDDDDDDDDDDGGGGGGGGGGGGGG";
    int i=0;

    [COLOR=seagreen]/* Kleinbuchstaben in Großbuchstaben umwandeln */    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;
}
```



^^ Hm, wenn man sich die Ausgaben so anschaut, fällt auf, dass immer die Anzahl der A nach den unerwünschten Buchstaben stimmt. Er fängt offenbar irgendwo draußen hinter dem Feld zu schreiben an und kommt dann nur bis irgendwo in der Mitte. Wie genau soll ich das ändern?

Gerade gemerkt: Wenn mind. 1 Buchstabe >100 mal vorkommt, stimmt alles. Nur, wenn kein Buchstabe >100 Mal vorkommt, kommt die fehlerhafte Ausgabe ...  

*[EDIT5]*
Fehler gefunden: Die Funktion checkLength liefert nicht die korrekte Länge zurück. Ich hätte es jetzt so umgeschrieben, aber ganz stimmt's immer noch nicht:

```
int checkLength(char *s) {
    int i=0, k=0, temp1=0, count1=0, count2=0, length1=0, length2=0;

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

    i=length1;
    while (i>0) {
        if (*(s+i)>=48 && *(s+i)<=57) { [COLOR=seagreen]/* Zahl gefunden. */            k++;
            count1=(*(s+i)-48); 
            count2+=(count1*(int)pow(10., k-1));
            if (*(s+i-1)>=65 && *(s+i-1)<=90) {
                temp1=count2;
                count2=0;
                k=0;
            }
            i-=calcSteps(temp1);
            length2+=temp1;
        } else if (*(s+i)>=65 && *(s+i)<=90) { [COLOR=seagreen]/* Buchstabe gefunden */            length2++;
            count2=0;
        }
        i--;
        
    }

    return length2;
}
```


----------



## boss3D (8. Dezember 2012)

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

So, habe den Code jetzt zu 95 % fertig und er liefert für nahezu alle Strings das richtige Ergebnis. Nur beim Decodieren von so ganz kurzem Zeug wie ABB, oder nur Einfachvorkommen, wie ABC wird alles um eine Stelle verschoben ausgegeben. Ergo habe ich den ersten Buchstaben doppelt und der letzte wird abgeschnitten. Das würde ich noch gerne lösen. 

Irgendwie hängt's mit i=length1; in decode_runlength() zusammen. Ich schreibe ich nämlich i=length1-1;, stimmen alle kurzen Ketten, dafür sind die langen wieder um eins zu weit nach links verschoben. Das muss sich doch irgendwie beides machen lassen?! Kann ja nicht sein, dass ich mich zwischen korrekten langen Ketten und korrekten kurzen Ketten entscheiden muss ...



Spoiler





```
#include <stdio.h>
#include <math.h>

int checkLength(char *s) {
    int i=0, j=0, k=0, temp1=0, count1=0, count2=0, length1=0, length2=0;

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

    i=length1; [COLOR=seagreen]/* length1 = Länge des codierten Strings. */    while (i>0) { [COLOR=seagreen]/* Es muss von hinten begonnen werden, weil nur so die char Ziffern bei der int-Berechnung die richtigen Stellenwerte erhalten. */        if (*(s+i)>=48 && *(s+i)<=57) { [COLOR=seagreen]/* Zahl gefunden. */            k++;
            count1=(*(s+i)-48); 
            count2+=(count1*(int)pow(10., k-1)); [COLOR=seagreen]/* Berechne Gesamtzahl als integer. */            if (*(s+i-1)>=65 && *(s+i-1)<=90) {
                length2+=count2;
                length2--;[COLOR=seagreen] /* Zahlen geben bereits Vorkommen des jeweiligen Buchstabens an. Dieser darf nicht auch noch dazugezählt werden. */            }
        } else if (*(s+i)>=65 && *(s+i)<=90) { [COLOR=seagreen]/* Buchstabe gefunden. */            length2++;
            count2=0;
            k=0;
        }
        i--;
    }

    return (length2-temp1+1);
}

[COLOR=seagreen]/* 
Funktion calc nötig, um Zahlenstellen in der richtigen Reihenfolge ausgeben lassen zu können 
durch verkleinern der entsprechenden Indexe von *s anhand des Rückgabewertes. 
*/int calcSteps(int num) {
    int temp1=num, temp2=0, count=0;

    while (temp1>0) {
        temp2=temp1%10;
        temp1/=10;
        count++; [COLOR=seagreen]/* Ermittle Anzahl der nötigen Rechenschritte und somit auch die Anzahl der Stellen der Zahl bzw. nötigen Indexe im Feld. */    }

    return count;
}

double encode_runlength(char *s) {
    int i=0, j=1, k=0, temp1=0, temp2=0, count1=0, count2=1, length=0;
    double ratio=0.0;

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

[COLOR=seagreen]    /* Codieren des Original-Strings: */    while (*(s+i) != '\0') {
        if (*(s+i)!=*(s+j)) { [COLOR=seagreen]/* Sobald Buchstabe nicht mehr gleich seinem Nachfolger ist, prüfe: */            if ((j-count1)==1) { [COLOR=seagreen]/* Einmaliges Vorkommen? */                *(s+k)=*(s+i); [COLOR=seagreen]/* Überschreibe Feld von vorne beginnend mit Buchstaben ... */                k++; [COLOR=seagreen]/* ... und springe im Index um 1 weiter. */                count1=j;
            } else { [COLOR=seagreen]/* Mehrmaliges Vorkommen? */                *(s+k)=*(s+i); [COLOR=seagreen]/* Überschreibe Feld von vorne beginnend mit Buchstaben. */                if ((j-count1)>9) { [COLOR=seagreen]/* Vorkommen größer als 9: */                    temp1=(j-count1);
                    while (temp1>0) { [COLOR=seagreen]/* Zerlege (An)Zahl in ihre einzelnen Stellen. */                        temp2=temp1%10;
                        temp1/=10;
                        count2++;[COLOR=seagreen] /* Zähle Rechenschritte mit um Anzahl der nötigen Stellen und somit Indexe zu ermitteln. */                        *(s+k+(calcSteps(temp1)+1))=(char)(temp2+48); [COLOR=seagreen]/* Überschreibe entsprechend viele Feldelemente mit den Stellen der Vorkommenszahl. */                    }
                    k+=count2; [COLOR=seagreen]/* Dann springe entsprechend viele Indexe weiter, um an die nächste zu überschreibende Stelle zu gelangen. */                    count1=j;
                    count2=1;
                } else {[COLOR=seagreen] /* Vorkommen bis 9: */                    *(s+k+1)=(char)((j-count1)+48);
                    k+=2; [COLOR=seagreen]/* Ein Buchstabe und seine Zahl wurden geschrieben. Springe daher 2 Indexe weiter. */                    count1=j;
                }
            }            
        }
        i++;
        j++;
    }
    ratio=(double)k; [COLOR=seagreen]/* ratio enthält am Ende der Schleife die Länge der Codierung. */    *(s+(int)ratio)='\0'; [COLOR=seagreen]/* Hänge an die Codierung noch eine Nullterminierung an. */
    printf("%s", s); [COLOR=seagreen]/* Ausgabe: Codierter String */
    return ((ratio*100)/(double)length);
}

int decode_runlength(char *s) {
    int i=0, j=0, k=0, temp1=0, temp2=0, count1=0, count2=0, length1=0, length2=0;
    
    while (*(s+length2)!='\0') {
        length2++;
    }
    
   [COLOR=seagreen] /* Decodiere String: */    
    length1=checkLength(s);
    [COLOR=royalblue][B]i=length1-1;[/B] [COLOR=seagreen]/* length1 = Originallänge des Strings. */    j=length2+1;[COLOR=seagreen] /* length2+1 = Länge des codierten Strings. */    while (i>0) {
        if (*(s+j)>=48 && *(s+j)<=57) {[COLOR=seagreen] /* Zahl gefunden. */            k++;
            count1=(*(s+j)-48); 
            count2+=(count1*(int)pow(10., k-1)); [COLOR=seagreen]/* Berechne Gesamtzahl als integer und ... */            if (*(s+j-1)>=65 && *(s+j-1)<=90) {
                temp1=(count2-1);
                temp2=count2;
            }
            while (temp1>0) {[COLOR=seagreen] /* ... überschreibe Feld von hinten beginnend gemäß dieser Anzahl mit dem zugehörigen Buchstaben. */                *(s+i)=*(s+j-calcSteps(temp2)+(k-1));
                temp1--;
                i--;
            }        
        } else if (*(s+j)>=65 && *(s+j)<=90) { [COLOR=seagreen]/* Buchstabe gefunden. */            *(s+i)=*(s+j);
            i--;
            count2=0;
            k=0;
        }
        j--;
    }
    *(s+length1)='\0';[COLOR=seagreen] /* Hänge an die Decodierung noch eine Nullterminierung an. */
    printf("%s", s); [COLOR=seagreen]/* Ausgabe: Decodierter String */
    return 0;
}

int main(void) {
[COLOR=seagreen]//int main(int argc, char *argv[]) {  [COLOR=seagreen]  //char *s = argv[1];    char s[] = "AB";
    int i=0;

    [COLOR=seagreen]/* Kleinbuchstaben in Großbuchstaben umwandeln */    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;
}
```



Hier zu Verdeutlichung, was ich meine:

*i=length1;* *--> lange Ketten stimmen, kurze um 1 verschoben.*




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        

 


			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



*i=length1-1; --> kurze Ketten stimmen, lange um 1 verschoben.

*


			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        

 


			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



^^ Hat dazu wer eine Idee?

Die Länge wird jedes mal und für jede Kette richtig ermittlet. Hab's extra noch einmal gecheckt. Nur für kurze Ketten fängt er offensichtlich um 1 nach hinten/rechts verschoben zu schreiben an. Jetzt stellt sich mir nur die Frage, wie der Compiler "kurz" definiert. Wenn ich genau wüsste, woran er die kurzen Ketten von den langen unterscheidet, könnte ich den Fehler beheben ...


----------



## bingo88 (8. Dezember 2012)

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

Mit zwei Änderungen läuft es bei mir durch:


```
#include <stdio.h>
#include <math.h>

int checkLength(char *s)
{
    int i = 0, j = 0, k = 0, count1 = 0, count2 = 0, length1 = 0,
            length2 = 0;

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

    /* FIX off by one */
    i = length1 - 1; /* length1 = Länge des codierten Strings. */
    while (i > 0)
    { /* Es muss von hinten begonnen werden, weil nur so die char Ziffern bei der int-Berechnung die richtigen Stellenwerte erhalten. */
        if (*(s + i) >= 48 && *(s + i) <= 57)
        { /* Zahl gefunden. */
            k++;
            count1 = (*(s + i) - 48);
            count2 += (count1 * (int) pow(10., k - 1)); /* Berechne Gesamtzahl als integer. */
            if (*(s + i - 1) >= 65 && *(s + i - 1) <= 90)
            {
                length2 += count2;
                length2--; /* Zahlen geben bereits Vorkommen des jeweiligen Buchstabens an. Dieser darf nicht auch noch dazugezählt werden. */
            }
        }
        else if (*(s + i) >= 65 && *(s + i) <= 90)
        { /* Buchstabe gefunden. */
            length2++;
            count2 = 0;
            k = 0;
        }
        i--;
    }

    return (length2 + 1);
}

/*
 Funktion calc nötig, um Zahlenstellen in der richtigen Reihenfolge ausgeben lassen zu können
 durch verkleinern der entsprechenden Indexe von *s anhand des Rückgabewertes.
 */
int calcSteps(int num)
{
    int temp1 = num, temp2 = 0, count = 0;

    while (temp1 > 0)
    {
        temp2 = temp1 % 10;
        temp1 /= 10;
        count++; /* Ermittle Anzahl der nötigen Rechenschritte und somit auch die Anzahl der Stellen der Zahl bzw. nötigen Indexe im Feld. */
    }

    return count;
}

double encode_runlength(char *s)
{
    int i = 0, j = 1, k = 0, temp1 = 0, temp2 = 0, count1 = 0, count2 = 1,
            length = 0;
    double ratio = 0.0;

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

    /* Codieren des Original-Strings: */
    while (*(s + i) != '\0')
    {
        if (*(s + i) != *(s + j))
        { /* Sobald Buchstabe nicht mehr gleich seinem Nachfolger ist, prüfe: */
            if ((j - count1) == 1)
            { /* Einmaliges Vorkommen? */
                *(s + k) = *(s + i); /* Überschreibe Feld von vorne beginnend mit Buchstaben ... */
                k++; /* ... und springe im Index um 1 weiter. */
                count1 = j;
            }
            else
            { /* Mehrmaliges Vorkommen? */
                *(s + k) = *(s + i); /* Überschreibe Feld von vorne beginnend mit Buchstaben. */
                if ((j - count1) > 9)
                { /* Vorkommen größer als 9: */
                    temp1 = (j - count1);
                    while (temp1 > 0)
                    { /* Zerlege (An)Zahl in ihre einzelnen Stellen. */
                        temp2 = temp1 % 10;
                        temp1 /= 10;
                        count2++; /* Zähle Rechenschritte mit um Anzahl der nötigen Stellen und somit Indexe zu ermitteln. */
                        *(s + k + (calcSteps(temp1) + 1)) = (char) (temp2 + 48); /* Überschreibe entsprechend viele Feldelemente mit den Stellen der Vorkommenszahl. */
                    }
                    k += count2; /* Dann springe entsprechend viele Indexe weiter, um an die nächste zu überschreibende Stelle zu gelangen. */
                    count1 = j;
                    count2 = 1;
                }
                else
                { /* Vorkommen bis 9: */
                    *(s + k + 1) = (char) ((j - count1) + 48);
                    k += 2; /* Ein Buchstabe und seine Zahl wurden geschrieben. Springe daher 2 Indexe weiter. */
                    count1 = j;
                }
            }
        }
        i++;
        j++;
    }
    ratio = (double) k; /* ratio enthält am Ende der Schleife die Länge der Codierung. */
    *(s + (int) ratio) = '\0'; /* Hänge an die Codierung noch eine Nullterminierung an. */

    printf("%s", s); /* Ausgabe: Codierter String */

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

int decode_runlength(char *s)
{
    int i = 0, j = 0, k = 0, temp1 = 0, temp2 = 0, count1 = 0, count2 = 0,
            length1 = 0, length2 = 0;

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

    /* Decodiere String: */
    length1 = checkLength(s);
    i = length1 - 1; /* length1 = Originallänge des Strings. */
    /* FIX off by one */
    j = length2 - 1; /* length2+1 = Länge des codierten Strings. */
    while (i > 0)
    {
        if (*(s + j) >= 48 && *(s + j) <= 57)
        { /* Zahl gefunden. */
            k++;
            count1 = (*(s + j) - 48);
            count2 += (count1 * (int) pow(10., k - 1)); /* Berechne Gesamtzahl als integer und ... */
            if (*(s + j - 1) >= 65 && *(s + j - 1) <= 90)
            {
                temp1 = (count2 - 1);
                temp2 = count2;
            }
            while (temp1 > 0)
            { /* ... überschreibe Feld von hinten beginnend gemäß dieser Anzahl mit dem zugehörigen Buchstaben. */
                *(s + i) = *(s + j - calcSteps(temp2) + (k - 1));
                temp1--;
                i--;
            }
        }
        else if (*(s + j) >= 65 && *(s + j) <= 90)
        { /* Buchstabe gefunden. */
            *(s + i) = *(s + j);
            i--;
            count2 = 0;
            k = 0;
        }
        j--;
    }
    *(s + length1) = '\0'; /* Hänge an die Decodierung noch eine Nullterminierung an. */

    printf("%s", s); /* Ausgabe: Decodierter String */

    return 0;
}

int main(void)
{
//int main(int argc, char *argv[]) {
    //char *s = argv[1];
    char s[] = "ABBBBBBBBAAAAAAAAACCCCCCCCCCCCCCCCCCD";
    //char s[] = "ABB";
    int i = 0;

    /* Kleinbuchstaben in Großbuchstaben umwandeln */
    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;
}
```
Ich habe die Stellen mit /* FIX ... */ markiert. Du hast jeweils bei einem Element zu früh angefangen (Array-Index beginnt bei 0 und nicht bei 1, d. h. du darfst nur von 0 bis len - 1 bzw. len - 1 bis 0 laufen). Dazu ist Einzelschritt-Debugging ganz hilfreich: Einfach ein paar Breakpoints an geeigneten Stellen setzen, sich durchhangeln und die Schritte mit dem kodierten String vergleichen.


----------



## boss3D (8. Dezember 2012)

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

^^ Vielen herzlichen Dank!  
Macht natürlich Sinn, was du schreibst. Breakpoints hätte ich auch gesetzt gehabt und Debuggen tue ich immer, wenn ich Fehler suche, nur waren meine Breakpoints wohl an anderen Stellen, als deine, weil ich den Fehler ganz woanders vermutet hatte ...

Habe ich das Beispiel endlich fertig!


----------



## bingo88 (8. Dezember 2012)

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

Ja, das mit dem Debuggen ist manchmal ein wenig tricky. Da hilft eigentlich nur Erfahrung und ausprobieren ^^ Freut mich aber, dass es bei dir jetzt auch funktioniert


----------



## boss3D (8. Dezember 2012)

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

Was mir gerade noch aufgefallen ist: Wir sagen jetzt in checkLength(): i=length1-1; und am Ende dann length2+1. Für meine Logik könnte man daher das -1 und das +1 streichen. Ein erster Test bestätigt dies. Möchte aber noch weitertesten, bevor ich's wirklich mache ...

*[EDIT]*
Am Lauflängencodierungscode kann man wohl doch nichts mehr ändern. Habe noch einiges getestet; der Code ist wirklich final. 

Eine andere Frage:
Wir habe hier vor langer Zeit mal eine Häufigkeitsanalyse geschrieben und die habe ich mir heute wieder angeschaut. Habe da jetzt was dazuprogrammiert, dass er überprüft, ob eh eine korrekte Parameterzahl (genau 2. 1 --> Programmaufruf, 2 --> Zu überprüfender Satz) eingegeben wurde. Wenn nicht, soll das Programm abbrechen. Allerdings wird immer nur die erste Fehlermeldung vom if ausgegeben ("Missing parameters") und ich komm' nicht drauf, warum. Eingegeben wird's doch so in die cmd: Programmname "Zu ueberpruefender Satz."

Programmname = erster Parameter
alles innerhalb der Anführungszeichen = zweiter Parameter
^^ ???

```
#include <stdio.h>
#include <stdlib.h>

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

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

void analyzeString(char *s) {
    int charCount[27]={0}, i=0, j=0, k=0, counter=0, ascii=0, length=checkLength(s);
    float percentage=0.0;

    [COLOR=seagreen]/* Anzahl der Buchstaben des Satzes und deren Häufigkeit ermitteln: */    while (i!=length) {
        if (*(s+i)>='A' && *(s+i)<='Z') {
            ascii=((int)*(s+i))-65; [COLOR=seagreen]/* int Werte von Großbuchstaben in den Bereich zwischen 0 und 25 runterrechnen. */        } else if (*(s+i)>='a' && *(s+i)<='z') {
            ascii=((int)*(s+i))-97; [COLOR=seagreen]/* int Werte von Kleinbuchstaben in den Bereich zwischen 0 und 25 runterrechnen. */        } else {
            ascii=((int)*(s+i)); [COLOR=seagreen]/* Sonderzeichen haben Werte außerhalb des Bereichs 0 bis 25. */            charCount[26]++; [COLOR=seagreen]/* Für jedes Sonderzeichen wird Wert im letzten Feldelement inkrementiert. */        }
        if (ascii>=0 && ascii<=25) {
            counter++;
            charCount[ascii]++;[COLOR=seagreen] /* Wert an der Stelle des Feldindex (0 bis 25) des jeweiligen Buchstaben wird bei Vorkommen inkrementiert */        }
        i++;
    }

    printf("Character count: %d (100 %%)\n", counter);
    printf("\nDetailled Frequence Analysis:\n");
    printf("\n  : count : percentage\n======================\n");
    for (j='a', k=0; j<='z', k<=25; j++, k++) {
        percentage=(((float)charCount[k]*100)/(float)counter);
        printf("%c :%6d :%11.2f\n", j, charCount[k], percentage);
    }
    putchar('\n');
}

[COLOR=royalblue][B]int main(int argc, char *argv[]) {
    char *s = argv[1];

    if (argc=1) {
        printf("Invalid input! Missing parameter.\n");
        exit(1);
    } else if (argc>2) {
        printf("Invalid input! Too many parameters.\n");
        exit(1);
    } else {
        analyzeString(s);
    }[/B]
    return 0;
}
```


----------



## retarDeD.aNiMaL (8. Dezember 2012)

If argc == 1 muss es heißen.... sonst setzt du es ja 1.


----------



## boss3D (8. Dezember 2012)

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

^^ Ah ja, wie peinlich! Ist wohl der Schlafentzug der letzten Tage ... 

BTW: Habe doch noch Optimierungspotenzial bei der Lauflängencodierung gefunden. Die ganze calcSteps() Funktion müsste man durch geschicktes Dekrementieren an den richtigen Stellen ersetzen können. Muss das noch ausprobieren. Statt pow müsste auch ein mehrfaches k*=10 möglich sein. Mal schauen, was da noch geht.

Bleibt für's erste nur meine Frage zu den komplexen Zahlen im Raum: Wie genau interpretiert ihr den Satz aus der Angabe *(Achte auch auf die konkrete Verwendung von Blanks!)* ? Hier mein Code:

```
#include <stdio.h>

typedef struct {
    float real;
    float imaginary;
} komplex_t;

void print_komplex(komplex_t *k) {
    if (k->real==0 && k->imaginary!=0) {
        printf("( %.2fi )\n", k->imaginary);
    } else if (k->imaginary==0 && k->real!=0) {
        printf("( %.2f )\n", k->real);
    } else if (k->real==0 && k->imaginary==0) {
        printf("( %.0f )\n", 0);
    } else if (k->real!=0 && k->imaginary!=0) {
        if (k->real>0 && k->imaginary>0) {[COLOR=seagreen] /* + + */            printf("( %.2f + %.2fi )\n", k->real, k->imaginary);
        } else if (k->real<0 && k->imaginary<0) { [COLOR=seagreen]/* - - */            k->real*=-1;
            k->imaginary*=-1;
            printf("( - %.2f - %.2fi )\n", k->real, k->imaginary); 
        } else if (k->real<0 && k->imaginary>0) { [COLOR=seagreen]/* - + */            k->real*=-1;
            printf("( - %.2f + %.2fi )\n", k->real, k->imaginary);
        } else if (k->real>0 && k->imaginary<0) { [COLOR=seagreen]/* + - */            k->imaginary*=-1;
            printf("( %.2f - %.2fi )\n", k->real, k->imaginary);
        }
    }
}

komplex_t add_k(komplex_t *k1, komplex_t *k2) {
    komplex_t res = { k1->real+k2->real, k1->imaginary+k2->imaginary };

    return res;
}

komplex_t sub_k(komplex_t *k1, komplex_t *k2) {
    komplex_t res = { k1->real-k2->real, k1->imaginary-k2->imaginary };

    return res;
}

komplex_t mul_k(komplex_t *k1, komplex_t *k2) {    
    komplex_t res = { k1->real*k2->real-k1->imaginary*k2->imaginary, k1->real*k2->imaginary+k1->imaginary*k2->real };

    return res;
}

komplex_t div_k(komplex_t *k1, komplex_t *k2) {
    komplex_t res = { (k1->real*k2->real+k1->imaginary*k2->imaginary)/(k2->real*k2->real+k2->imaginary*k2->imaginary), 
                      (k1->imaginary*k2->real-k1->real*k2->imaginary)/(k2->real*k2->real+k2->imaginary*k2->imaginary) };

    return res;
}

int main(void) {
    komplex_t *res;
    komplex_t komplex_1 = { 0, 0 };
    komplex_t komplex_2 = { 1.23, 0 };
    komplex_t komplex_3 = { 0, 3.14 };
    komplex_t komplex_4 = { -2.34, 1 };
    komplex_t komplex_5 = { -3, 4 };
    komplex_t komplex_6 = { 1, 3 };
    komplex_t komplex_7 = { 1, 1 };
    komplex_t result = { 0, 0 };
    res=&result;
    
    [COLOR=seagreen]/* Additionen */    *res=add_k(&komplex_1, &komplex_2);
    print_komplex(res);
    *res=add_k(&komplex_3, &komplex_4);
    print_komplex(res);
    
    [COLOR=seagreen]/* Subtraktionen */    *res=sub_k(&komplex_3, &komplex_4);
    print_komplex(res);
    *res=sub_k(&komplex_5, &komplex_6);
    print_komplex(res);

   [COLOR=seagreen] /* Multiplikationen */    *res=mul_k(&komplex_5, &komplex_7);
    print_komplex(res);
    *res=mul_k(&komplex_6, &komplex_7);
    print_komplex(res);

    [COLOR=seagreen]/* Divisionen */    *res=div_k(&komplex_1, &komplex_2);
    print_komplex(res);
    *res=div_k(&komplex_4, &komplex_6);
    print_komplex(res);

    return 0;
}
```
Heißt das nur, dass eben in der Ausgabe zwischen Rechenzeichen und Zahl ein Leerzeichen sein muss? Dann wäre das Ganze ja mit meinem (unschönen) if-else Konstrukt erledigt. Oder soll das heißen, dass ich meine float Zahlen zerlegen und in einen char string packen muss, und in diesem dann Indexe bis zum Rechenzeichen durchfahren, nachfolgende Zahl nach hinten schieben und ein char 'Leerzeichen' einfügen soll?
Was würdet ihr euch zu dieser Aufgabe als Abgabe erwarten, wenn ihr der Lehrer wärt?

Ich persönlich würde die Aufgabe als erledigt entsprechend der Angabe betrachten, aber vielleicht sieht das jemand anders?!


----------



## retarDeD.aNiMaL (8. Dezember 2012)

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

hier stand quark


----------



## boss3D (12. Januar 2013)

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

Ich habe ein paar Frage zu Einfach Verketteten Listen. Dazu auch ein Code-Beispiel:

Diesmal geht's nur um Erklären, nichts Programmieren ... 

Hier startet die Verkettete Liste (main):

```
typedef struct element {
    int id; [COLOR=seagreen]/* Element id */    char * daten; [COLOR=seagreen]/* Datenfeld des Listenelementes */    struct element *next; [COLOR=seagreen]/* Zeiger auf das naechste Listenelement */} Element;

int main() {
    int max = 10;
    Element *liste = NULL; [COLOR=seagreen]/* Anker der Liste im Hauptprogramm */    int i;
    
    [COLOR=seagreen]/* Liste mit 10 Elementen anlegen */    for (i=0;i<max;i++)
        liste = element_einfuegen (liste, i, "Wirf den Ring ins Feuer");
        
   [COLOR=seagreen] /* Inhalt aller Elemente schreiben */    for (i=0;i<max;i++)
        element_schreiben(liste, i);
    
    [COLOR=seagreen]/* Element zur Liste fuegen */    liste = element_einfuegen(liste, 11, "Wirf Schneewittchen ins Feuer");
    
    [COLOR=seagreen]/* Element aus der Liste loeschen */    element_loeschen(liste, 5);
    
   [COLOR=seagreen] /* Freigeben der Listenelemente */    free_liste (liste);
    
    printf ("end\n");
}
```
^^ Da ist noch alles klar.
*
Einfügen eines Elements:*

```
[COLOR=seagreen]/*
* Element * element_einfuegen (Element *liste, int id, char *text) - Erstellt ein
* neues Element (Mit id und *text) und fuegt es am Anfang der Liste ein.
* @*liste: Zeiger auf den Beginn der Liste
* @id: Identifier des neuen Listenelements
* @*text: Textinhalt des neuen Listenelements
* @return: Zeiger auf das neue erste Element der Liste oder im Fehlerfall die
* bisherige Liste
*/Element * element_einfuegen (Element *liste, int id, char *text) {
    Element *helper = (Element*) malloc (sizeof(Element));
    printf("Element: %d einfuegen\n", id);
    
    if (helper == NULL) {
        printf("Fehler: Speicherprobleme\n");
        return liste;
    }

    [COLOR=darkorchid]helper->id = id;
    helper->daten = text;
    helper->next = NULL;
   [COLOR=seagreen] /* neues Element wird an den Anfang der Liste gesetzt */    [COLOR=darkorchid]helper->next = liste;    printf("Element: %d eingefuegt Daten: %s\n", [COLOR=darkorchid]helper->id, helper->daten);

    return helper;
}
```
^^ 
1. Was genau macht Element *helper hier bzw. wofür brauche ich das? Ist Element *helper das neue Listenelement, das am Anfang der Liste eingefügt wird?
2. Was genau bekommen die jeweiligen Komponenten des zusammengesetzten Datentyps helper in den lila Zeilen zugewiesen? id und text, die der Funktion übergeben werden? 
3. Und wieso setze ich den Zeiger zuerst auf NULL, wenn das neue Element doch am Anfang der Liste eingefügt werden soll? Nur der Zeiger des letzten Listenelements zeigt auf NULL?! Und danach plötzlich auf liste? "liste" steht hier für das zweite Listenelement, oder? Und somit wäre helper dann das erste und würde auf das zweite verweisen?! 
4. Und im printf werden den Komponenten von helper wieder die Werte, die der Funktion übergeben werden, zugewiesen, oder wie?

*Suchen von Elementen:*

```
[COLOR=seagreen]/*
* Element * element_suchen (Element *liste, int id) – Sucht
* das Element mit der id in der Liste liste
* @*liste: Zeiger auf das erste Element der Liste
* @id: Identifier des zu suchenden Listenelements
* @return: ein Zeiger auf das gesuchte Element oder NULL, falls das
* Element nicht in der Liste enthalten ist
*/Element * element_suchen (Element *liste, int id){
    [COLOR=darkorchid]Element * result = liste;    
    printf("Element: %d suchen\n", id);

    while ((result != NULL) && [COLOR=darkorchid](id != result->id))
        [COLOR=darkorchid]result = result->next;
    if (result != NULL) 
        printf("Element: %d gefunden\n", result->id);

    return result;
}
```
^^
1. Kann man einfach einem struct ein anderes zuweisen, oder was genau passiert in der ersten lila Zeile? Wieso soll liste laut Kommentar nur ein Zeiger sein? next ist doch der Zeiger in dem struct?!
2. Die while Schleife soll laufen, bis entweder das Ende der verketteten Liste erreicht ist, oder die id des gesuchten Elements und somit das Element selbst gefunden wurde. Aber was genau sind die zwei id's hier? Das erste id ist wohl das, das an die Funktion zum Suchen übergeben wird, aber das zweite?
3. Und die dritte lila Zeile: Wie genau muss ich das verstehen? Der next pointer von result soll immer um ein Element weiter zeigen, aber wie/wo wird next weitergesetzt, wenn das gesuchte Element im jeweiligen Schleifendurchlauf noch nicht gefunden wurde?

*Löschen eines Elements:*

```
[COLOR=seagreen]/*
* int element_loeschen (Element *liste, int id) - Sucht das Element
* mit der id in liste und loescht dieses
* @*liste: Zeiger auf das erste Element der Liste
* @id: Identifier des zu löschenden Elements
* @return: Liste ohne geloeschtes Element
*/Element * element_loeschen (Element *liste, int id) {
    [COLOR=darkorchid]Element *delElem = liste , *vorgaenger = NULL;    printf("Element: %d loeschen\n", id);

    while ((delElem != NULL) && (id != delElem->id)) {
        [COLOR=darkorchid]vorgaenger = delElem;
        delElem = delElem->next;    }

    if (delElem == NULL)
        printf("Element nicht gefunden\n");
    else [COLOR=darkorchid]if (vorgaenger == NULL) {
        liste = delElem->next;        printf("Element: %d wird geloescht\n", delElem->id);
        free (delElem);
    } else {
        [COLOR=darkorchid]vorgaenger->next = delElem->next;        printf("Element: %d wird geloescht\n", delElem->id);
        free (delElem);
    }
    
    return liste;
}
```
^^
1. Hier verstehe ich auch wieder die lila Zeilen nicht wirklich. Ich weiß auch nicht genau, was ich fragen soll. Erklärt mir bitte einfach wozu das, was passiert, passieren muss.

*Ausgabe eines Elements:*

```
[COLOR=seagreen]/*
* int element_schreiben(Element *liste, int id) – Gibt den Inhalt 
* eines Elements (id und *daten) aus. 
* @*liste: Zeiger auf das erste Element der Liste 
* @id: Identifier des auszugebenden Elements 
* @return: 0 falls die Ausgabe erfolgreich war, 1 falls das Element 
* nicht gefunden wurde 
*/ int element_schreiben(Element *liste, int id) { 
    Element *elm = NULL; 
    
    printf("Element: %d schreiben\n", id); 
    
    elm = element_suchen (liste, id); 
    
    if (elm == NULL) 
        return 1; 
    else { 
        printf("Element: %d Daten: %s\n", elm->id, elm->daten); 
        return 0; 
    } 
}
```
^^ Das ist wieder klar.


----------



## fadade (12. Januar 2013)

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

Einfügen:
Helper ist halt das neue Element, was eingefügt werden soll. Der helper ist natürlich jetzt natürlich nur ein Speicherbereich ohne Funktion! Die Daten ID/Text/Next-Element machen den Bereich halt für dich in der verketteten Liste nutzbar und deswegen setzt du da ID/Text auf die Parameterwerte.
Warum jetzt das Next-Element zuerst auf NULL und dann auf nen gültigen Wert gesetzt wird weiß ich nicht, vielleicht weil in dem Speicher vorher (vor setzen auf NULL) nur KrimsKrams drinsteht und du damit sichergehst, dass das überschrieben wird, aber das machst du eigentlich dann auch mit setzen auf liste --> auf NULL finde ich da überflüssig^^

Suchen:
Result ist der zeiger auf das Element, das die gesuchten Daten enthält. Und wie sucht man? Richtig man setzt in der ersten violetten Zeile Den Zeiger auf das erste Listenelement (bzw. den Zeiger darauf).
Falls du irgendwann bei der richtigen ID (id = gesuchte id und Bedingung ist id == result->id, weil das ja immer das aktuell betrachtete Litenelement repräsentiert) angekommen bist, enthält result den Zeiger auf das Element, falls es die ID nicht gibt, ist result = NULL, weil das letzte Element der Liste ja NULL als Next-Element hat --> Abbruchbedingung
Vielleicht ist Punkt 3 so einfacher zu verstehen:

```
int find(int wert)
{
    int result = 0;
    while(result != NULL oder sonstwas && result != wert)
    {
          result = result + 1;
    }
    return result; // result == wert, sinnlos, aber vielleicht ja repräsentativ^^
}
```

Das gleiche Vorgehen wendest du halt auch auf die Liste an, nur dass du da die IDs vergleichst, Abbruch ist NULL=result und result = result + 1 ist halt das Next-Element von result immer.


Löschen:
Du brauchst einmal wieder das aktuelle Element und einmal den Vorgänger, weil stell dir mal die Liste so vor:
AABBABAAACBBABAA
Und jetzt löschst du "C"!
Dann musst du schauen, wann du bei "C" angekommen bist (im obigen Code wieder ID-Vergleich) und dann entsprechen vom Vorgänger "A" das NextElement auf "C"->NextElement setzen, denn wenn du C löschst musst du die entstandene "Lücke" ja überbrücken, sonst würde deine Liste immer wieder mitten in der Wallachei aufhören 

Konkreter Fall:
delElem = "C"
vorgänger = "A" (also ein bestimmtes)

Die obere Schleife bricht ab, weil C != NULL und IDs stimmen überein. Nun füllst du halt je nach Fall (direkt Start der Liste/mittendrin/Ende der Liste) die entstandene Lücke auf.

Hoffe ist einigermaßen verständlich^^


----------



## boss3D (13. Januar 2013)

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

Ok, danke! Bis auf das Löschen des Elements habe ich alles einigermaßen verstanden ...

Dazu noch einmal:

```
Element * element_loeschen (Element *liste, int id) {
    [COLOR=darkorchid]Element *delElem = liste , *vorgaenger = NULL;    printf("Element: %d loeschen\n", id);

    while ((delElem != NULL) && (id != delElem->id)) {
        [COLOR=darkorchid]vorgaenger = delElem;
        delElem = delElem->next;    }

    if (delElem == NULL)
        printf("Element nicht gefunden\n");
    else [COLOR=darkorchid]if (vorgaenger == NULL) {
        liste = delElem->next;        printf("Element: %d wird geloescht\n", delElem->id);
        free (delElem);
    } else {
        [COLOR=darkorchid]vorgaenger->next = delElem->next;        printf("Element: %d wird geloescht\n", delElem->id);
        free (delElem);
    }
    
    return liste;
}
```
Das if ist klar --> Das Element, das gelöscht werden soll, gibt's gar nicht. Aber was ist der Unterschied zwischen dem else if und dem else? In beiden Fällen wird was gelöscht ...


----------



## fadade (13. Januar 2013)

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

_if (delElem == NULL) _--> Element nicht Existent
_else if (vorgaenger == NULL) _--> delElem ist ERSTES Element der Liste.
Beispielfall: CAABB ist Liste und du möchtest C löschen. Jetzt kommst du da an delElem ist C und vorgänger ist NULL, weil da halt noch nix is.
C wird gelöscht und Liste müsste ja mit A anfangen, und das ist delElem->next (was dann der neue Listenanfang ist)

_else _--> wie im obigen Post erwähnt, "Lücke" des Löschens füllen.
Bsp1: AACBAAB muss ja in AABAAB resultieren und AABAABC[NULL] müsste ja in AABAAB[NULL] resultieren


----------



## boss3D (13. Januar 2013)

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

Achso, der Anker einer verketteten Liste ist ebenfalls NULL (sieht man in der main). Nicht nur der Zeiger des letzten Elementes. Jetzt wird das klarer ...

Ok, danke! Das reicht mir für's erste. Wenn noch Fragen auftauchen, melde ich mich wieder.


----------



## boss3D (24. April 2014)

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

Ich bräuchte einen Code, der mir aus einem vorgegebenen Buchstaben-String alle möglichen Kombinationen (mit Mehrfachvorkommen) berechnet. In der Fachsprache "Permutation MIT Wiederholung" genannt. 
Irgendwo in meinen Ansätzen dürfte ich einen Denkfehler drinnen haben, weil am Ende immer wieder nur eine Permutation OHNE Wiederholung rauskommt. Und man findet auch nur das (in allen möglichen Programmiersprachen) im Internet, weshalb ich auch keine vernünftigen Code-Beispiele habe, an denen ich mich orientieren könnte.

Das hier z. B. wäre ne perfekte Permutation OHNE Wiederholung. Nur wie bastle ich das so um, dass ich eine MIT WH habe? 

```
#include <stdio.h>
#include <string.h>

void swap(char a[], int i, int j) {
    char temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}

void permut(char a[], int endIndex) {
    int i = 0;

    if (endIndex == 0) {
        printf("%s\n", a);
    } else {
        permut(a, endIndex-1);
        for (i = 0; i <= endIndex-1; i++) {
            swap(a, i, endIndex);
            permut(a, endIndex-1);
            swap(a, i, endIndex);
        }
    }
}

int main(void) {
    char str[] = "ahlo";
    int maxIndex = strlen(str)-1;

    permut(str, maxIndex);

    return 0;
}
```
Ich verlange auch nicht, dass mir jetzt wer einen fertigen Code "hinknallt", sondern ich wäre schon über Lösungsansätze und Ideen froh ...
(Ober rekursiv oder iterativ ist auch egal)


----------



## Rho (24. April 2014)

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



boss3D schrieb:


> Und man findet auch nur das (in allen möglichen Programmiersprachen) im Internet


 
Dann ist dein Internet wohl kaputt. In meinem Internet hab ich reichlich dazu gefunden. Zum Beispiel das: c++.de :: Permutationen


----------



## boss3D (24. April 2014)

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

^^ Auf der Seite war ich schon, aber ich krieg's nicht hin, den passenden Code richtig nach C umzuschreiben. Ich schau mir das morgen nochmal an ...


----------



## b14ckj4ck (25. April 2014)

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



boss3D schrieb:


> Ich bräuchte einen Code, der mir aus einem vorgegebenen Buchstaben-String alle möglichen Kombinationen (mit Mehrfachvorkommen) berechnet.


bin mir nicht ganz sicher ob ich das richtig verstanden habe, aber der Code gibt dir für die Zeichenkette "ab" mit einer Ziellänge von 2 das hier aus:


```
aa
ab
ba
bb
```




Spoiler





```
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

const char* text = "ab";

/**
 * Permutation mit Wiederholungen
 * @param string zu permutierender String
 * @param strLen Laenge des strings
 * @param desLen Laenge der zu erstellenden Permutationen
 */
void permute(const char* string, int strLen, int desLen) 
{
	int number[desLen];
	char out[desLen];
	int i = 0;
	int j = 0;
	const int max = desLen * (strLen-1);
	while(i != desLen) 
	{
		number[i] = 0;
		out[i] = string[0];
		++i;
	}	

	printf("%s\n", out);
	i = 0;

	while(i != max) 
	{
		while(1)
		{
			++i;
			if(++number[j] < strLen)
			{
				out[j] = string[number[j]];
				break;
			}

			i -= strLen;
			out[j] = string[0];
			number[j] = 0;
			++j;
		}
		j = 0;

		printf("%s\n", out);
	}
}


int main(int argc, char** argv) 
{
	permute(text, strlen(text), 2);
	return 0;
}
```





mfg b14ckj4ck


----------



## boss3D (25. April 2014)

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

^^ Ja, danke! Das ist jetzt eine Permutation mit Wiederholung. Nur zwei Probleme hat der Code in dieser Form laut Visual Studio:

1) Irgendwo wird offenbar eine Feldgrenze überschritten?!




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.
        



2) Auch wenn ich das ebenso gemacht hätte, das hier wird rot unterwellt, weil desLen ein "constant value" sein muss:

```
void permute(const char* string, int strLen, int desLen) {
    int number[[COLOR=red]desLen];
    char out[[COLOR=red]desLen];
```
Muss ich jetzt wirklich ein dynamisches Array dafür erstellen, oder lässt sich das noch anders lösen? Bzw. mit einem Macro müsste es auch gehen, wäre aber ebenso wenig "ellegant".


----------



## b14ckj4ck (25. April 2014)

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



boss3D schrieb:


> ^^ Ja, danke! Das ist jetzt eine Permutation mit Wiederholung. Nur zwei Probleme hat der Code in dieser Form laut Visual Studio:
> 
> 1) Irgendwo wird offenbar eine Feldgrenze überschritten?!
> 
> ...


Das Problem ist, dass dein String vermutlich kein null-Charakter besitzt. Das Problem sollte durch 
	
	



```
a[length] = '\0';
```
 gelöst werden können.



```
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

const char* text = "ahlo";

/**
* Permutation mit Wiederholungen
* @param string zu permutierender String
* @param strLen Laenge des strings
* @param desLen Laenge der zu erstellenden Permutationen
*/
void permute(const char* string, int* number, char* out, int strLen, int desLen)
{
	int i = 0;
	int j = 0;
	const int max = desLen * (strLen - 1);
	while (i != desLen)
	{
		number[i] = 0;
		out[i] = string[0];
		++i;
	}

	printf("%s\n", out);
	i = 0;

	while (i != max)
	{
		while (1)
		{
			++i;
			if (++number[j] < strLen)
			{
				out[j] = string[number[j]];
				break;
			}

			i -= strLen;
			out[j] = string[0];
			number[j] = 0;
			++j;
		}
		j = 0;

		printf("%s\n", out);
	}
}

int main(int argc, char** argv)
{
	int length = strlen(text);
	char* a = malloc((length + 1) * sizeof(char));
	a[length] = '\0';
	int* n = malloc(length * sizeof(int));
	permute(text, n, a, strlen(text), length);
	free(a);
	free(n);
	getchar();
	return 0;	
}
```

Ausgabe:


Spoiler





```
aaaa
haaa
laaa
oaaa
ahaa
hhaa
lhaa
ohaa
alaa
hlaa
llaa
olaa
aoaa
hoaa
loaa
ooaa
aaha
haha
laha
oaha
ahha
hhha
lhha
ohha
alha
hlha
llha
olha
aoha
hoha
loha
ooha
aala
hala
lala
oala
ahla
hhla
lhla
ohla
alla
hlla
llla
olla
aola
hola
lola
oola
aaoa
haoa
laoa
oaoa
ahoa
hhoa
lhoa
ohoa
aloa
hloa
lloa
oloa
aooa
hooa
looa
oooa
aaah
haah
laah
oaah
ahah
hhah
lhah
ohah
alah
hlah
llah
olah
aoah
hoah
loah
ooah
aahh
hahh
lahh
oahh
ahhh
hhhh
lhhh
ohhh
alhh
hlhh
llhh
olhh
aohh
hohh
lohh
oohh
aalh
halh
lalh
oalh
ahlh
hhlh
lhlh
ohlh
allh
hllh
lllh
ollh
aolh
holh
lolh
oolh
aaoh
haoh
laoh
oaoh
ahoh
hhoh
lhoh
ohoh
aloh
hloh
lloh
oloh
aooh
hooh
looh
oooh
aaal
haal
laal
oaal
ahal
hhal
lhal
ohal
alal
hlal
llal
olal
aoal
hoal
loal
ooal
aahl
hahl
lahl
oahl
ahhl
hhhl
lhhl
ohhl
alhl
hlhl
llhl
olhl
aohl
hohl
lohl
oohl
aall
hall
lall
oall
ahll
hhll
lhll
ohll
alll
hlll
llll
olll
aoll
holl
loll
ooll
aaol
haol
laol
oaol
ahol
hhol
lhol
ohol
alol
hlol
llol
olol
aool
hool
lool
oool
aaao
haao
laao
oaao
ahao
hhao
lhao
ohao
alao
hlao
llao
olao
aoao
hoao
loao
ooao
aaho
haho
laho
oaho
ahho
hhho
lhho
ohho
alho
hlho
llho
olho
aoho
hoho
loho
ooho
aalo
halo
lalo
oalo
ahlo
hhlo
lhlo
ohlo
allo
hllo
lllo
ollo
aolo
holo
lolo
oolo
aaoo
haoo
laoo
oaoo
ahoo
hhoo
lhoo
ohoo
aloo
hloo
lloo
oloo
aooo
hooo
looo
oooo
```





mfg b14ckj4ck


----------



## boss3D (25. April 2014)

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

Okay, so funktioniert's dann in dem Code, aber ich muss mir das jetzt erst überlegen, ob ich das wirklich alles genau so brauche. Ich bastle nämlich an was größerem, wovon dieser Code nur ein Teil ist, den ich jetzt integrieren muss ...


----------



## bingo88 (25. April 2014)

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



boss3D schrieb:


> 2) Auch wenn ich das ebenso gemacht hätte, das hier wird rot unterwellt, weil desLen ein "constant value" sein muss:
> 
> ```
> void permute(const char* string, int strLen, int desLen) {
> ...


 Statische Arrays werden auf dem Stack angelegt, daher muss die Größe zur Compile-Zeit bekannt (also const) sein. Also entweder feste Länge oder ein dynamisches Array verwenden.


----------



## boss3D (25. April 2014)

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

Jetzt scheitert's eigentlich nur noch am Vergleich. Obwohl das PW gefunden werden müsste, findet die Ausgabe nicht statt ... 

(Beispielhafte) Usereingabe in die Kommandozeile: _./code -l 5 -c ahlo d3751d33f9cd5049c4af2b462735457e4d3baf130bcbb87f389e349fbaeb20b9_ (Klartext zum Hash wäre hier "hallo")

@ bingo88
Danke, hab's schon gemerkt.


----------



## bingo88 (25. April 2014)

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

Oh, du machst da was ganz böses. Deine sha256 gibt einen Zeiger auf eine lokale Variable zurück. Wenn die Funktion verlassen wird, wird diese Variable ungültig und du hast einen dangling pointer. Der strcmp Aufruf dereferenziert dann diesen Pointer, aber da kann schon wieder was ganz anderes drinnen stehen (weswegen dann eventuell auch der Vergleich fehlschlägt).

Entweder du machst die Variable static, dann bleibt sie erhalten, oder du erzeugst ein dyn. Array (was du dann später aber wieder löschen musst). Die static-Variante hat den Nachteil, dass die Variable beim nächsten Funktionsaufruf überschrieben wird (gleicher Zeiger -> anderer String). Das kann zu extrem unschönen Bugs führen.

Edit: Abgesehen davon hast du eine globale Variable "hash" und eine lokale mit demselben Namen. Oft wird bei globalen ein "g_" vorangestellt, um Namenskollisionen zu vermeiden.


----------



## DarkMo (25. April 2014)

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

wieso wusste ich nur, dass du die nsa hacken willst!


----------



## boss3D (25. April 2014)

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

Hui, hab's jetzt so probiert:

```
unsigned char hash = malloc(SHA256_DIGEST_LENGTH * sizeof(char));
```
Aber da kriege ich unschöne Rückmeldungen ...
error: subscripted value is neither array nor pointer


DarkMo schrieb:


> wieso wusste ich nur, dass du die nsa hacken willst!


Na ja, sooo viele Anwendungszwecke für Permutationen gibt's dann auch nicht. War wohl schnell klar, wofür ich's brauchen würde?! 

*[Edit]*
_*faceplam*_

Sternchen vergessen: unsigned char* ...

Trotzdem kriege ich immer noch keine Ausgabe von wegen PW gefunden.


----------



## bingo88 (25. April 2014)

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



boss3D schrieb:


> Hui, hab's jetzt so probiert:
> 
> ```
> unsigned char hash = malloc(SHA256_DIGEST_LENGTH * sizeof(char));
> ...


unsigned char *hash 

Hast du meinen letzen Edit auch gesehen?


----------



## boss3D (25. April 2014)

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

Auf's fehlende Sternchen bin ich schon selber drauf gekommen und die globale Variable heißt jetzt g_hash, danke. Trotzdem kriege ich immer noch nicht "PW gefunden! PW = hallo" ausgegeben ...

Außerdem kriege ich (schon die ganze Zeit) "warning: pointer targets in return differ in signedness", was auch immer das heißen soll. So ein warning habe ich überhaupt noch nie gesehen.
Irgendwas mit signed und unsigned passt nicht zusammen.


----------



## bingo88 (25. April 2014)

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



boss3D schrieb:


> Außerdem kriege ich (schon die ganze Zeit) "warning: pointer targets in return differ in signedness", was auch immer das heißen soll. So ein warning habe ich überhaupt noch nie gesehen.
> Irgendwas mit signed und unsigned passt nicht zusammen.


 return value: (signed) char
hash: unsigned char

Entweder hash oder den return value anpassen.

Edit: Notfalls nen cast von unsigned char auf char *hust*


----------



## boss3D (25. April 2014)

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

Die sha256 Funktion unsigned zu machen bringt auch nichts. Genau so wenig, wie das unsigned vor char* hash zu löschen. Ich weiß auch nicht, wo ich das free(hash) hintun soll. Nach dem return kann ich es schlecht einfügen, aber in der main geht's auch nicht, weil unser hash Array ja lokal in sha256() ist ...

Und das eigentliche Problem bleibt, dass nach wie vor Übereinstimmungen der Hashes nicht erkannt werden?!


----------



## bingo88 (25. April 2014)

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



boss3D schrieb:


> Die sha256 Funktion unsigned zu machen bringt auch nichts. Genau so wenig, wie das unsigned vor char* hash zu löschen. Ich weiß auch nicht, wo ich das free(hash) hintun soll. Nach dem return kann ich es schlecht einfügen, aber in der main geht's auch nicht, weil unser hash Array ja lokal in sha256() ist ...


Ich habe jetzt einfach mal den return Wert gecastet, nur damit die Warnung verschwindet:

```
return (char*)hash;
```

An dem anderen arbeite ich gerade ^^


----------



## DarkMo (25. April 2014)

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

und wenn ihr den hash mittels call-by-reference der sha256 funke übergebt? dann habt ihr in der main direkt den zeiger auf den hash bla blubb. wisst scho, wie ichs mein ^^ dann könnt ihr den auch aus der main heraus freigeben *denk*


----------



## bingo88 (25. April 2014)

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

So, ich habe das jetzt mal grob überarbeitet. Ich habe nicht auf alles geachtet, hier sind ein paar Punkte:


Jedes malloc braucht irgendwann ein free
malloc mit size = 0 ist uncool (bei dir mit inputLen = 0 geschehen)
Dyn. Arrays mit der richtigen Größe anlegen. Wenn in deinen Command Line  Args die Größenangaben drinnen stehen, kannst du das Array erst  anlegen, nachdem du diese Größe hast.
Off-by-one Fehler: Wenn der SHA256 als String 64 Zeichen lang ist, brauchst du 65 Zeichen Speicher (wegen dem Nullzeichen am Ende - kann man zwar weglassen, da verlassen sich aber einie Funktionen drauf, dass das da ist - strcmp zum Beispiel)
Generell: Fehlerbehandlung, z. B. return values von malloc != NULL. Habe jetzt auch nicht alles eingebaut (ohne Cmd line args gibt es übrigens ein SIGSEGV), ich wollte ja "nur" den Bug fixen...
sha256: Das SHA256_Final liefert dir den binären Hash, daher auch das unsigned char. Du musst das erst wieder in einen Hex-String umwandeln, damit das mit strcmp später klappt.


----------



## boss3D (25. April 2014)

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

Okay, unklar ist mir dabei folgendes:

In sha256():
- Die for-Schleife brauche ich nicht mehr und will ich weg haben. Aber dann funktioniert das ganze nicht mehr (wenn ich auch hash lösche, das ja eh nur darin vorkommt, und bei return rawHash angebe)?! Wieso ist die so wichtig?
- Was könnte ich aus sha256() alles rausschmeißen, damit die Funktion wirklich nur noch den Hash berechnet und zurückgibt? i und alles mit *hash, oder?

Meine for-Schleife in der main() soll prüfen, ob nach der Auswertung der Kommandozeile durch getopt() noch irgendwas übrig ist. In unserem Fall der eingegebene Hash. Dieser wird dann einfach in die globale Variable g_hash gespeichert. Und das funktioniert ja auch.


----------



## bingo88 (25. April 2014)

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



boss3D schrieb:


> - Die for-Schleife brauche ich nicht mehr und will ich weg haben. Aber dann funktioniert das ganze nicht mehr (wenn ich auch hash lösche, das ja eh nur darin vorkommt, und bei return rawHash angebe)?! Wieso ist die so wichtig?


Jo klar, die wandelt dir ja auch den binären Hashwert ("Rohwerte") in eine Hex-Repräsentation (Hex-String) um. Wenn du die weglässt, kannst du natürlich nicht mehr mit strcmp vergleichen, da dein Eingabe-Hash ja ein Hex-String und kein binärer Hash ist. Äpfel mit Birnen vergleichen und so 



boss3D schrieb:


> Was könnte ich aus sha256() alles rausschmeißen, damit die Funktion  wirklich nur noch den Hash berechnet und zurückgibt? i und alles mit  *hash, oder?


Kurz: nichts. Lang: siehe unten


```
char* sha256(char *string) {
         int i = 0; // Schleife
         SHA256_CTX sha256; // SHA256
         unsigned char rawHash[SHA256_DIGEST_LENGTH]; // SHA265 - Rohe Hashwerte
         char *hash = NULL; // SHA256 - Hash als Hex-String 

         // Alles SHA256
         SHA256_Init(&sha256);
         SHA256_Update(&sha256, string, strlen(string));
         SHA256_Final(rawHash, &sha256); 

         // Speicher für Hex-String (Zruückgeben eines Zeigers auf eine lokale Variable hatten wir ja schon)
         hash = malloc(65 * sizeof(char)); 

         // Konvertiert binären Hash in Hex-String (gleiches Format wie Vergleichsstring)
         for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
                 sprintf(hash + (2 * i), "%02x", rawHash[i]);
         }         

         // Nullzeichen setzen
         hash[64] = '\0'; 

         // Der char* cast kann hier weg, den hatte ich noch übersehen...
         return hash;
 }
```


----------



## boss3D (25. April 2014)

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

^^ Ich habe gerade rausgefunden, woher mein Denkfehler kam: Ich dachte, sprintf würde, genau wir printf, was ausgeben. Tut's aber nicht. Stattdessen werden Daten nur in einem Buffer gespeichert. Jetzt ist auch klar, warum ich die Schleife brauche und das nicht rausschmeißen kann.

Ich überleg mir dann mal den MPI Teil ...


----------



## bingo88 (25. April 2014)

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

Jupp, das klingt nachvollziehbar


----------



## boss3D (27. April 2014)

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

Durch mpi habe ich es zwar geschafft, dass alle Nodes arbeiten, aber leider machen die bei mir alle das selbe, anstatt die Berechnungen sinnvoll untereinander zu verteilen ...

Davon abgesehen, habe ich noch folgendes erfahren/rausgefunden:
- Statt dem SH256 Init/Update/Final gäb's anscheinend auch eine einzige für uns notwendige SHA256() Funktion?! Allerdings finde ich dazu absolut nichts auf google, und was ich auch eingebe, ich habe entweder zu viele, zu wenige, oder ungültige Parameter.
- Das, was wir dann in der for-Schleife in sha256() machen, ist angeblich höchst ineffizient (Hex Strings Vergleichen). Stattdessen sollten wir das besser in Byte Strings umwandeln und die dann bspw. mit XOR vergleichen. Hierzu finde ich zwar das, aber die scheinen sich nicht einig zu sein, wer denn nun eine brauchbare Lösung gefunden hat?! 

^^ Die beiden Punkte sind jetzt nicht sooo tragisch. Der Code mag ineffizient sein, aber er macht zumindest schon mal das richtige. Mir wäre sehr geholfen, wenn mir bitte wer bei der Verteilung auf 3 Nodes mit mpi helfen könnte.

*[Edit]*
Man könnte vielleicht über diese Formel die Anzahl aller möglichen Zeichen-Kombinationen aus dem Charset berechnen, und die dann durch die Anzahl der Nodes dividieren. Anschließend jede Node 1/3 berechnen lassen?!

Ich habe jetzt eine Fakultäts-Funktion eingebaut und unten in der main() herumgewerkt, aber v. a. das if-else Konstrukt macht natürlich noch nicht, was es soll. Da müssten jetzt noch die jeweiligen Drittel rein. Außerdem würden sich die Nodes derzeit alles gegenseitig überschreiben, wenn die mit den selben Arrays arbeiten?!




			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.


----------

