C programmieren

schroedinger87

Cadet 1st Year
Registriert
Dez. 2021
Beiträge
8
Hallo liebe C-Spezialisten.

Ich habe folgende Aufgabenstellung zum Collatz-Problem (3n+1):

1. Schreiben Sie ein Programm das zwei zahlen m und p einließt und daraus eine Collatz Zahlenfolge bildet.

2. Es muss auch ausgeben welches die größte Zahl ist, die in ihren Schritten enthalten ist. Parameter max.

3. Das Programm muss folgende Prozedur implementieren und verwenden: void converge (int n, in *steps, int *max); . das

4. Es sollen die Anzahl der Schritte im Parameter steps gespeichert werden, welche benötigt werden um das Problem zu lösen.

Mein Code bisher:

#include <stdio.h>

int main(void) {
int m;
int p;

printf("Erste Zahl eingeben: ");
scanf("%d", &m);
printf("Zweite Zahl eingeben: ");
scanf("%d", &p);

printf("Collatz-Reihe von %d: \n", m);
while(m != 1) {
if(m%2 == 0) {
m = m / 2.0;
printf("%d\n", m);
}
else {
m = 3 * m + 1;
printf("%d\n", m);
}
}
printf("Collatz-Reihe von %d: \n", p);
while(p != 1) {
if(p%2 == 0) {
p = p / 2.0;
printf("%d\n", p);
}
else {
p = 3 * p + 1;
printf("%d\n", p);
}
}
return 0;
}

Punkt 1 funktioniert. Doch wie bekomme ich den Rest mit Maximalwert und Anzahl der Schritte hin?
 
Zuletzt bearbeitet:
Erstmal das Programm so umbauen, dass es Punkt 3 erfüllt, dann weitergucken.
 
  • Gefällt mir
Reaktionen: schroedinger87
Vielen Dank für die schnellen Antworten.
Ich bin Anfänger in C.
@Don_2020 Was bewirke ich mit steps?
@jlnprssnr Die Sachen in Punkt 3 sagen mir leider nicht viel. Ich hab das Programm nach meinem bisherigen Wissensstand geschrieben.
 
Der Parameter "steps" ist im Punkt 4 definiert.

Lesen und verstehen. Deshalb gibt es Übungsaufgaben.
 
  • Gefällt mir
Reaktionen: BeBur
Also soweit ich das verstehe sind "steps" und "max" nur die Namen für die Parameter.
Doch wie bekomme ich eine Anzahl bzw. den Maximalwert in diese Parameter?
 
Zählen wäre eine Möglichkeit.
Glaskugel und Raten die beiden anderen möglichen Wege.
Nicht jeder Weg führt zum Ziel.

Selber Denken erleichtert das Leben ungemein.
Denken verursacht keine bleibenden Schäden. Über Nebenwikrungen ist in der mir bekannten Literatur nichts bekannt.
Einfach mal probieren.

Viel Erfolg!

PS: Wann ist Abgabe?
 
  • Gefällt mir
Reaktionen: BAGZZlash und sh.
dann so ;)
C:
int steps = rand();
Aber im Ernst, Steps musst du halt einen hochzählen, immer wenn du eine mathematische Operation machst. Und Max jeweils immer gucken, ob die neu errechnete Zahl größer ist oder nicht als die vorher in Max gespeicherte
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: schroedinger87
1. "Collatz", nicht "Colliatz".
2. Code bitte in Code-Tags.
3. "C programmieren" ist ein denkbar schlechter, generischer Thread-Titel. Bitte demnächst was Aussagekräftiges nehmen.
 
  • Gefällt mir
Reaktionen: schroedinger87
@BAGZZlash Okay, sorry. Ich werde beim nächste Mal besser darauf achten, den Code in die Tags zu schreiben und einen prägnanteren Titel für meinen Thread wählen.

@Don_2020 Ich lerne. C Programmieren ist Neuland für mich. Aus diesem Grund habe ich meine Frage ins Forum gestellt, da man über den Austausch mit Leuten die die nötige Erfahrung haben, am Besten lernt. Ich brauche C für mein Studium, da es ein Teilgebiet bei den Grundlagen ist. Kein Grund beleidigend zu werden.

Den Thread aus 2010 den du verlinkt hast, habe ich auch schon gefunden, allerdings ist die Aufgabenstellung ein bisschen anders und C erkennt den Befehl ulam nicht. Außerdem möchte ich es selbst schreiben und verstehen und nicht kopieren.

Danke trotzdem an alle. Schönen Abend und einen Guten Rutsch.
 
  • Gefällt mir
Reaktionen: BAGZZlash
Don_2020 schrieb:
Das mit dem Programmieren solltest Du besser aufgeben. Internetrecherche ist auch nicht deine Stärke.
Vielleicht steckt in dir ein begnadeter Pizzabäcker?
Nix gegen Pizzabäcker, aber jeder sollte das machen was einem liegt.
Immer mit der Ruhe. Die Mehrheit aller Menschen hat mit kleinen Schritten und Hilfe angefangen irgendwas zu lernen. Sei es in der Schule, Studium, Ausbildung oder im Beruf.
Personen, welche ohne jegliche Vorkenntnisse, rein intuitiv und ohne Hilfe 3. z.B. gut Programmieren können sind sehr selten. Wenn Sie zu der Gruppe gehören ist das schön, rechtfertigt aber nicht andere Personen bei Problemen gleich so anzufahren.

@schroedinger87

Bei : " void converge (int n, int *steps, int *max); " handelt es sich um eine Funktion mit 3 übergebenen Parametern.
" n " wird die Startzahl sein.
" *steps " die Anzahl der Schritte bis zu Lösung (für Aufgabenteil 4)
" *max " Maximalwert in der Folge (für Aufgabenteil 3)

Falls der Unterschied von Call by Reference zu Call by Value noch nicht bekannt ist hier ein Beispiel mit Erklärung dazu.
"n" wird als Call by Value an die Funktion " converge "übergeben. Das bedeutet, wenn für die Variable der Wert aus "m" oder "p" übergeben wird, dass dieser in "n" Kopiert wird. Falls der Wert "n" verändert wird, hat dies keinerlei Auswirkung auf "m" oder "p".
" steps " und " *max " werden hingegen als Call by Rerference an die Funktion übergeben, zu erkennen an dem "" vor dem Namen der Variable. Der Unterschied zu Call by Value ist, dass hierbei die Adresse auf die Variable übergeben wird.

C:
int schritte = 10;
int *steps = &schritte;
printf("%d \n",steps);
printf("%d \n",*steps);
*steps = 20;
printf("%d \n",steps);
printf("%d \n",*steps);
printf("%d \n",schritte);

Das Beispiel erzeugt die Variable "schritte" vom Typ int und schreibt die Zahl 10 in die Variable.
Danach wird der Zeiger "steps" vom Typ int angelegt. Mit "&schritte" wird die Adresse von "schritte" dem Zeiger "steps" zugeordnet.
"printf("%d \n",steps);" gibt die in "steps" enthaltene Adresse aus. " \n" sorgt für einen anschließenden Zeilenumbruch.
mit "*" vor dem Zeiger kann auf den Inhalt der Variable zugegriffen werden. "printf("%d \n",*steps);" gibt so den Wert der Variable aus.
Genau so kann man auch den Wert der Variable verändern, im Beispiel habe ich den Wert auf 20 geändert. Die Adresse bleibt identisch und beim "printf" von "schritte" sieht man, dass sich dieser ebenfalls geändert hat.


Die Funktion muss im Code vor der Hauptfunktion "main()" und nach der Inkudierung (#include <xyz>) platziert werden. Sollte von der Form her so aussehen:

C:
#include <stdio.h>

void myfunc(int var_a, int *var_b){

// hier der Quellcode mit dem Algorithmus der Funktion
 
}

int main(){

    int b = 10;
    int c = 20;

    int *val;
    myfunc (b, &val);

    myfunc (c,&val);

    return 0;
}

Hier ist das auch nochmal erklärt: Link


Wegen dem Zählen der Schritte in Abschnitt 3 kann man einfach zu Begin der Funktion "converge(...)" den Wert von "steps" auf 0 setzten und zu Begin jeden Durchlaufs der While-Schleife wird der Wert um eins erhöht. Beispiel mit Variable "k":
C:
k = k + 1; // normales Zählen
*k = *k +1; // Zählen mit Zeiger

Zu Abschnitt 4. Die Funktion läuft unendlich lang. Irgendwann erfolgt die wiederholende Abfolge "4,2,1". Dafür muss man den aktuellen Wert + die zwei vorherigen behalten.
Mit "break" kann man eine Schleife abbrechen. Das muss man mit einer if-clause Kombinieren und kann so gezieht die Schleife beenden.
Mit "true" erzeuge ich nachfolgend eine Dauerschleife und wenn die Variablen "a=4" b=2" und "c=1" sind wird die Schleife abgebrochen.
Da muss man einen Algorithmus schreiben, welcher in "a" den aktuellen, in "b" den vorherigen und in "c" den Wert vor "b" speichert.

C:
while(true){

    // hier steht der Algorithmus
 
    if(a==4 && b==2 && c==1) break;
}

Viel Spaß beim Programmieren und falls Fragen auftreten einfach stellen.
 
  • Gefällt mir
Reaktionen: schroedinger87
Also so sieht mein Code mittlerweile aus. Hab ihn etwas vereinfacht und anders als in der Aufgabenstellung die Funktion nicht verwendet, da ich damit nicht zurecht gekommen bin.
Den Maximalwert sowie die Berechnung kriege ich so jetzt hin.
Nur weiss ich keine Lösung wie ich auf diese Weise Die Anzahl der Schritte heraus bekomme.
Gibt es dafür Tipps?

C:
#include <stdio.h>

int main(void)    {
    int m;
    int iMaxValue = 0;
    int c = 0;
    
    printf("Zahl eingeben: ");
    scanf("%d\n", &m);
    printf("Collatz Reihe: \n", m);
    while(m != 1)    {
        if(m%2 == 0)    {
            m = m / 2.0;
            printf("%d\n", m);
            if(m > iMaxValue)    {
                iMaxValue = m;
            }
            else    {
                m = 3 * m + 1;
                printf("%d\n", m);
                if(m > iMaxValue)    {
                    iMaxValue = m;
            }
        }
        printf("Groesste Zahl ist : %d\n", iMaxValue);
        return 0;
    }
 
Dieser Code kompiliert doch nicht einmal.

Hier mal etwas zur Unterstützung, sozusagen als Startpunkt für weitere Überlegungen, auf Grundlage Deines Codes:

C:
#include <stdio.h>

int main(void)
{
    int m;
    int Steps = 0;
    
    printf("Bitte eine positive, ganze Zahl eingeben: ");
    scanf("%d", &m);
    
    printf("Collatzreihe:\n");
    
    while (m != 1)
    {
        Steps++;
        printf("%d\n", m);
        
        if (m % 2 == 0)
        {
            m = m / 2.0;
        }
        else
        {
            m = (3 * m) + 1;
        }
    }
    
    printf("1\nAnzahl Schritte: %d\n", Steps);
    
    return(0);
}
 
Sieht doch schon brauchbar aus. Waren 3 kleine Fehler enthalten. 2 Klammern haben gefehlt und bei dem Ersten Parameter von "scanf" ist "\n" kein gültiger Wert. Die Funktion erzeugt automatisch einen Zeilenumbruch, da braucht man das "\n" nicht ;)

C:
#include <stdio.h>

int main(void) {
    int m;
    int iMaxValue = 0;
    int c = 0;

    printf("Zahl eingeben: ");
    scanf("%d", &m);     // hier kein \n, Zeilenumbruch erzeugt die Funktion von selbst
    printf("Collatz Reihe: \n", m);
    while(m != 1) {
      if(m%2 == 0) {
        m = m / 2.0;
        printf("%d\n", m);
        if(m > iMaxValue) {
          iMaxValue = m;
          }
       }    // hier hat die Klammer der ersten If-Anweisung gefehlt
       else {
         m = 3 * m + 1;
         printf("%d\n", m);
         if(m > iMaxValue) {
           iMaxValue = m;
         } // hier hat die Klammer der inneren if-Anweisung gefehlt
       }
    }
    printf("Groesste Zahl ist : %d\n", iMaxValue);
    return 0;
}


Wenn ich mit 19 starte erhalte ich die Folge: 58, 29, 88, 44, 22, 11, 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1 und das Maximum wird mit 88 ebenfalls richtig ausgegeben.
Bei 11 erhalte ich die Folge: 34, 17, 52, 26, 13, 40, 20, 10, 5, 16, 8, 4, 2, 1 mit Maximum 52.
Sieht soweit schon mal ganz gut aus.

Zum Zählen habe ich schon den Tipp gegeben. Zu Begin der Schleife die Zähl-Variable um 1 erhöhen. Beispiel für eine Variable oder einen Zeiger stehen in meinem vorherigen Beitrag.


Der nächste Schritt ist es den Algorithmus (while-Schleife) in die Funktion "converge" auszulagern.
Ich würde hier einfach die Funktion vor "main()" einfügen und die Parameter zunächst weg lassen ->
C:
void converge(void){


}

Wenn der Code dann ohne Probleme durch den Compiler läuft, in die Funktion ein "printf" mit irgendeinem Text einfügen, z.B. " printf("Hallo Welt");" und den Code compilieren.
Wenn es keine Probleme gibt die Funktion innerhalb der "main()" mit "converge();" aufrufen.
Wenn alles klappt sollte auf der Konsole "Hallo Welt" ausgegeben werden.

Im nächsten Schritt die Funktion um den ersten Parameter erweitern: "void converge(int n)". Beim Aufruf daran denken, dass nun auch eine Integer-Variable in der Klammer übergeben werden muss, z.B. "m".
Dann den Code wieder compilieren und schauen, ob es Probleme gibt. Wenn nicht ein "printf" nutzen um in der Funktion den Wert von "n" auf der Konsole auszugeben und überprüfen, ob der Wert korrekt ist.

Danach kann man dann den Algorithmus aus "main" in "converge" verschieben. Daran denken, dass die Funktion nur die Variablen kennt, welche als Parameter oder innerhalb der Funktion selbst definiert wurden. Das "m" aus "main()" kennt die Funktion nicht. Genauso wenig kennt "main()" das "n" aus der Funktion.


Wenn das ganze dann Funktioniert kann man zuletzt noch die Zeiger "int *steps" und "int *max" als Parameter der Funktion einpflegen. Das würde ich erst ganz zum Schluss machen.
Aber ein Schritt nach dem anderen.
Ich würde mit mit dem Zähler anfangen und dann die Funktion, wie ich beschrieben habe, schrittweise aufbauen.
 
Zurück
Oben