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

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
Code:
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.
 
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! :daumen:
Werde noch einiges programmieren in den Ferien und wenn ich wieder wo anstehe, melde ich mich wieder ...
 
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:
Code:
#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?
 
Zuletzt bearbeitet:
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

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

Code:
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

Code:
char* string_arr[] = {"abc", "acb" ,"bac", "bca", "cab", "cba"/*,NULL*/};
 
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

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 ... :fresse:
Code:
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. ;)
 
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

Code:
        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.
 
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.
 
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 ...
Code:
[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:
Code:
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:
error.JPG

Und ich mit meinem beschränkten Zeigerverständnis sehe leider die Fehlerquelle im Code nicht ...
 
Zuletzt bearbeitet:
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.

Code:
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:

Code:
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;
}
 
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

Ah, ok ...

Hier jetzt das ganze Programm mit Zeigern:
Code:
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?
Code:
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?
 
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.
 
Zuletzt bearbeitet:
AW: [C] Hochzahlen ohne math.h und pow berechnen ...

Ok, vielen Dank! Jetzt ist einiges klarer ... :)
 
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.
Code:
[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 ... :huh:
 
Zuletzt bearbeitet:
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.
 
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. :)
 
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. :what:
Code:
#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?
 
Zuletzt bearbeitet:
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.
Code:
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
Code:
// ä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)
 
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* ><
 
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 ^^
 
Zurück