Anfänger braucht Hilfe...



  • hallo und guten tag,

    kurz zu mir:
    ich bin Maschinenbau-Student und habe im ersten Semester den Kurs
    Einführung in die Programmiersprache C
    abgesehen von schwerfälligen Gehversuchen im Bereich Turbo-Pasqual
    hab ich mit Programmieren noch nichts zu tun gehabt...
    aber ich bin lernfähig!

    soviel zu meinem wissensstand.

    mein problem ist nun,
    dass ich im Rahmen einer Bonusaufgabe (Klausur-Extrapunkte) ein Programm zum Berechnen von bestimmten Integralen
    auf die Beine stellen soll!
    soweit so gut:
    das Programm steht noch nicht so wirklich gerade, denn das Herzstück fehlt noch...
    die Berechnung!!!
    das Integral soll mit Hilfe von Trapezen berechnet werden...
    auch das ist noch nicht das Problem...
    rein mathematisch stehen die Überlegungen schon ganz gut!

    nun zur eigentlichen Frage:

    die Gesamtfläche errechnet sich aus der Summe
    der einzelnen Teilflächen A0 bis An
    dafür brauche ich alle einzelne Y-Werte Y0 bis Yn
    dafür wiederrum brauche ich alle einzelne X-Werte X0 bis Xn
    n ist dabei die Anzahl der Teiflächen,
    die vom Bennutzer eingegeben werden soll

    jetzt aber wirklich zur Frage 😉

    Wie kann ich diese einzelnen Werte aus einer Schleife rausziehen,
    und dann in die nächste einfügen?

    Ich bin damit wirklich schon ne Weile beschäftigt...
    aber es überschreitet eindeutig meinen Horizont!!! 😕

    habs auch schon ma mit arrays probiert,
    jedoch,so glaube ich,kann man die Feldgröße nicht mit n deklarieren!?

    zum besseren Verständnis hier ma der Link zur Aufgabe:
    http://www.thull-online.eu/data/fh/WS2006/Bonusaufgabe_zur_Vorlesung_EINF_2006.pdf

    es sei deutlich gesagt, es soll mir keiner meine Hausaufgaben machen!!!
    ich brauch lediglich den einen Hinweis,
    wie das mit den einzelnen Werten funktioniert...

    falls sich jemand die Mühe machen will...
    schon ma im voraus vielen dank



  • Ich versteh deine Frage nicht so ganz. Du gibst in einer Schleife n Werte ein (?). Die willst du in der nächsten folgenden benutzen (?). Aber wo ist da dein Problem? Wenn du ein Array außerhalb der Schleife deklarierst ist dies doch für die ganze Funktion gültig und damit auch verfügbar...



  • Ich denke er meint zwei while-Schleifen wie etwa so:

    do
    {
        // Eingabe der Koeffizienten und Grenzen hier
        do
        {
            // Eingabe der Teilintervalle hier
            // Berechnung und Ausgabe...
            // Frage, nach neuen Teilintervallen, wenn ja --> Schleifenanfang
        }
        while ( neue_teilintervalle == JA );
        // Frage, ob neue Berechnung
    }
    while ( programm_beenden == NEIN );
    

    "Rausziehen" musst Du die Werte dabei garnicht. Sie werden einfach in Variablen gespeichert, die du dann verwenden kannst.



  • Danke erstma für eure Hilfsbereitschaft!!!

    zum Problem:

    zuerst müssten die X-Werte berechnet werden..
    dass sollte meiner Meinung nach so funktionieren...

    Xo = untere Grenze des Teilintervalls
    X1 = Xo + Breite eines Teilintervalls

    diese schleife soll solange laufen bis Xn (sprich obere Teilgrenze) erreicht ist...

    dann sollen die Y-Werte berechnet werden..
    ungefähr so..

    Yo = a * Xo² + b * Xo + c

    bis

    Yn = a * Yn² + b * Yn + c

    zum Berechnen von Yo bis Yn brauche ich also die werte von Xo bis Xn
    wenn das mit einem bzw mehreren arrays gehen soll, müsste das Array n Felder haben..
    das hat bei mir jedoch nicht funktioniert...??
    und wie weise ich denn die jeweiligen X-Werte einem Platz im Array zu??

    mfg



  • tzuio schrieb:

    habs auch schon ma mit arrays probiert,
    jedoch,so glaube ich,kann man die Feldgröße nicht mit n deklarieren!?

    du kannst die gösse des arrays nicht zur laufzeit bestimmen, soll heissen: der wert in den eckigen klammern, der die anzahl der arrayelemente darstellt muss eine zahl oder eine konstante sein. du kannst aber trotzdem zur laufzeit speicher z.b. für eben ein solches array reservieren. die funktionen sind

    int *ptr=(int*) malloc(sizeof(int)*n);
    

    (n ist hierbei die anzahl und ptr ein zeiger auf das erste element) und wennn du die grösse anpassen willst:

    realloc(ptr, new_n);
    

    nicht vergessen: am ende wieder mit

    free(ptr);
    

    den speicher wieder freigeben.



  • hm,
    gibs vielleicht eine andere Möglichkeit das problem zu realisieren... 😕
    ausser mit arrays mein ich
    z.B. mit einer Endlosschleife...und break
    aber wie weise ich dann die Ergebnisse der ersten Schleife Variablen zu, die ich dann in der nächsten Schleife wieder brauch??

    mfg



  • Mir war heute etwas langweilig und ich hab mich auch mal an der Aufgabe versucht.

    Ich denke das schwierigste an dem Programm ist die Berechnung selbst.
    Ich habe auch hin- und herüberlegt ob ich ein sehr großes statisches Array nehmen soll oder lieber dynamisch Speicherplatz reservieren.

    Doch eigentlich braucht man immer nur zwei Höhenwerte + Teilfläche was man zur Gesamtfläche addiert.

    Hier mal mein Vorschlag:

    ACHTUNG: Da sind vermutlich noch einige Fehler drin...

    /*	Name: integral.c
    		Autor: Simonek
    */		
    
    #include <bl01lib.h>			// Bindet nötige Header-Dateien + Zusatzfunktionen
    
    #define DEBUG JA				// DEBUG-MODUS ZEIGT ZWISCHENWERTE AN. AUF JA/NEIN STELLEN
    #define ID if(DEBUG==JA)	// MAKRO FÜR DEN DEBUG-MODUS
    
    #define TINT_MAX 5000			// Maximale Anzahl von Teilintervallen
    #define KMAX 100				// Größter Wert für Koeffizienten
    #define KMIN -100				// Kleinster Wert für Koeffizienten
    
    void funktion_anzeigen(int aufruf, double a, double b, double c);
    
    int main(void)
    {
    	double a = 'a', b = 'b', c = 'c'; 		// Koeffizienten
    	double lgrenze, hgrenze;							// Integrationsgrenzen (lower, higher)
    	int tint; 												// Anzahl der Teilintervalle
    
    	double lange;												// Länge der X-Achse zwischen den Integrationsgrenzen
    	double abstand;												// Abstand zwischen den Teilintervallen
    	double hohe[2];												// Zwischenspeicher für die Höhen
    	double flache;												// Zwischenspeicher für die Teilflächen
    
    	double integral;											// Die Gesamtfläche ==> Ergebnis
    
    	double num;											// X-Werte für die Höhenberechnung
    	int count;											// Counter für Schleifen
    
    	int neue_teilintervalle = JA;
    	int neue_berechnung = JA;
    
    /* STARTE MIT BENUTZEREINGABEN */
    	do 	
    	{ 
    			funktion_anzeigen(1, 'a', 'b', 'c');
    	    printf("Bitte geben Sie den ersten Koeffizienten ein\n\n==> ");
    	    a = d_eingabe(KMIN, KMAX);
    	    funktion_anzeigen(2, a, 'b', 'c');
    	    printf("Bitte geben Sie den zweiten Koeffizienten ein\n\n==> ");
    	    b = d_eingabe(KMIN, KMAX);
    	    funktion_anzeigen(3, a, b, 'c');
    	    printf("Bitte geben Sie den dritten Koeffizienten ein\n\n==> ");
    	    c = d_eingabe(KMIN, KMAX);
    	    funktion_anzeigen(4, a, b, c);
    	    printf("Integral von X = min. bis X = max.\n\n\n");
    	    printf("Bitte geben Sie die untere Grenze ein\n\n==> ");
    	    lgrenze = d_eingabe(KMIN, KMAX);
    	    funktion_anzeigen(4, a, b, c);
    	    printf("Integral von X = %4.2lf bis X = max.\n\n\n", lgrenze);
    	    printf("Bitte geben Sie die obere Grenze ein\n\n==> ");
    	    hgrenze = d_eingabe(KMIN, KMAX);
    	    funktion_anzeigen(4, a, b, c);
    	    printf("Integral von X = %4.2lf bis X = %4.2lf.\n\n\n", lgrenze, hgrenze);
    
    	    do 
    	    { 
    	    	printf("Bitte geben Sie die Anzahl der Teilintervalle ein\n\n==> ");	// Eingabe der Teilintervalle hier
    	   		tint = int_eingabe(1, TINT_MAX);
    	   		clrscr();
    
    /* STARTE MIT DER BERECHNUNG */
    
    /* BERECHNUNG DER LÄNGE AUF DER X-ACHSE */
    	   		if ( lgrenze < 0 && hgrenze <= 0 )
    	   			lange = (-1) * ( lgrenze - hgrenze );
    	   		else if ( lgrenze < 0 && hgrenze > 0 )
    	   			lange = ( (-1) * lgrenze ) + hgrenze;
    	   		else if ( lgrenze >= 0 && hgrenze > 0 )
    	   			lange = hgrenze - lgrenze;
    	   		else
    					lange = (-1);
    
    	   		if ( lange < 0 )
    	   		{
    	   			printf("Fatal Error - Ung%cltige Grenzen", ue);
    	   			return EXIT_FAILURE;
    	   		}
    
    	   		ID printf("\nL%cnge = \t%4.2lf\n", ae, lange);	
    
    /* BERECHUNG DER ABSTÄNDE DER TEILINTERVALLE */
    	   		abstand = (lange) / ((double)tint);
    	   		ID printf("Abstand = \t%lf\n\n", abstand);
    
    /* BERECHNUNG DER EINZELNEN HÖHEN SOWIE BERECHNUNG DER TEIL- UND GESAMTFLÄCHE*/
    				ID printf("\n");
    				num=lgrenze;
    				integral = 0;
    				flache = 0;
    				hohe[1] = 0;
    
    				hohe[0] = ( (a) * ( (num)*(num)) ) + ( (b) * (num) ) + (c);
    	      ID printf("%2d. H%che = %lf f%cr X = %lf\n", 1, oe, hohe[0], ue, num);
    	     	num += abstand;
    
    	      for(count = 1; count <= tint; count++)
    	      {
    	      	hohe[(count%2)] = ( (a) * ( (num)*(num)) ) + ( (b) * (num) ) + (c);
    	      	ID printf("%2d. H%che = %lf f%cr X = %lf\n", count+1, oe, hohe[(count%2)], ue, num);
    	      	num += abstand;
    	      	flache = ( ((hohe[((count-1)%2)]) + (hohe[(count%2)])) / 2 ) * (abstand);
    	      	if ( flache < 0 )
    	      		flache *= (-1);
    	      	integral += flache;
    	      	ID printf("%2d. Teilfl%cche = %5.3lf, Bisherige Gesamtfl%cche = %3.3lf\n\n", count, ae, flache, ae, integral);
    	      }
    
    /* AUSGABE DES INTEGRALS */
    				printf("\n\n\nDas Integral (%4.2lf bis %4.2lf) der Funktion:\n\n", lgrenze, hgrenze);
    				printf("f(x) = %4.2lfx%c + %4.2lfx + %4.2lf\n", a, 253, b, c);
    	      printf("\nbetr%cgt: ca. %5.4lf FE\n", ae, integral);
    	      printf("=======================\n\n\n");
    
    /* FRAGE, OB ANDERE ANZAHL VON TEILINTERVALLEN */
    	    	printf("Neue Anzahl von Teilintervallen (J)a/(N)ein?\n\n==> ");	// Frage, nach neuen Teilintervallen
    	    	neue_teilintervalle = jn_frage();
    
    	    } 
    	    while ( neue_teilintervalle == JA ); 
    /* FRAGE, OB WEITERE BERECHNUNG */
    	    printf("Wollen Sie eine neue Berechnung (J)a/(N)ein?\n\n==> "); // Frage, ob neue Berechnung 
    	    neue_berechnung = jn_frage();
    	} 
    	while ( neue_berechnung == JA ); 
    
    	return EXIT_SUCCESS;
    }
    
    void funktion_anzeigen(int aufruf, double a, double b, double c)
    {
    	clrscr();
    	printf("BESTIMMTE INTEGRALBERECHNUNG EINER BELIEBIGEN PARABEL\n\n");
    	printf("EINGABE DER DATEN:\n");
    	printf("==================\n\n");
    	if ( aufruf == 1 )
    		printf("\nDie Funktion lautet: f(x) = %cx%c + %cx + %c\n\n", (int)a, 253, (int)b, (int)c);
    	else if ( aufruf == 2 )
    		printf("\nDie Funktion lautet: f(x) = %4.2lfx%c + %cx + %c\n\n", a, 253, (int)b, (int)c);
    	else if ( aufruf == 3 )
    		printf("\nDie Funktion lautet: f(x) = %4.2lfx%c + %4.2lfx + %c\n\n", a, 253, b, (int)c);
    	else
    		printf("\nDie Funktion lautet: f(x) = %4.2lfx%c + %4.2lfx + %4.2lf\n\n", a, 253, b, c);
    	printf("\n");
    }
    

    In der "bl01lib.h" hab ich viele allgemeine Funktionen.
    Du brauchst eigentlich nur das:

    // bl01lib.h
    #ifndef _INC_STDIO		// BINDET HEADER-DATEIEN EIN
    	#include <stdio.h>
    #endif
    #ifndef _INC_STDLIB
    	#include <stdlib.h>
    #endif
    #ifndef _INC_STRING
    	#include <string.h>
    #endif
    #ifndef _INC_TIME
    	#include <time.h>
    #endif
    #ifndef _INC_CTYPE
    	#include <ctype.h>
    #endif
    #ifndef _INC_MATH
    	#include <math.h>
    #endif
    #ifndef _INC_STDARG
    	#include <stdarg.h>
    #endif
    
    #ifdef __unix__													// BILDSCHIRM LEEREN
        #define clrscr() printf("\x1B[2J")
    #elif __BORLANDC__ && __MSDOS__
        #include <conio.h>
    #elif __WIN32__ || _MSC_VER
        #define clrscr() system("cls")
    #else
        #define clrscr() new_screen()
    #endif
    
    #ifndef _BL01LIB_H
    #define _BL01LIB_H
    
    // DEUTSCHE UMLAUTE
    #define AE (unsigned char)142 
    #define ae (unsigned char)132 
    #define OE (unsigned char)153 
    #define oe (unsigned char)148 
    #define UE (unsigned char)154 
    #define ue (unsigned char)129 
    #define ss (unsigned char)225 
    
    #define JA 1
    #define NEIN 0
    
    int jn_frage(void);	
    long int_eingabe(long min, long max);
    void new_screen(void);
    double d_eingabe(double min, double max);
    
    int jn_frage(void)																// ÜBERSETZT J/N in 1/0
    {
    	char a = 'a';
    	char puf[20];
    
    	while ( strchr( "NnJj", a ) == NULL )
    		{
    					fgets(puf, 20, stdin);
    					a = *puf;
    		}
    
    		if (a == 'j' || a == 'J') {
    			return 1; 
    		}
    		else
    			return 0;
    }
    
    long int_eingabe(long min, long max)
    {
    	int count;
    	int austritt = 0;
    	int austritt2 = 0;
    	long var = (max+1);	// Variable, die zurückgegeben wird
    	int is_zahl = 0;
    
    	int tmp_int;
    	unsigned int lange = 0;
    	char tmp_string[20+1];
    
    while ( austritt2 == 0 )						// Legt Wertebereich fest
    {
    		while ( austritt == 0 )					
    		{	
    				printf("\0gabe ==> ");
    				fgets(tmp_string, (20+1), stdin);				// LIEßT STING EIN
    
    				lange = strlen(tmp_string);					
    				for(count=0; count<(lange-1); count++)		// lange-1, weil wir '\0' nicht vergleichen wollen
    				{
    					tmp_int = tmp_string[count];
    					is_zahl = isdigit(tmp_int);
    					if ( is_zahl == 0 )								// Wenn keine Ziffer --> Schleife startet neu
    					{
    						if ( (tmp_int == '-') && (count == 0) )
    						{
    							austritt = 1;
    						}
    						else
    						{
    							austritt = 0;
    							break;
    						}
    					}
    					else
    						austritt = 1;										// Wenn nur Ziffern --> Beendet Schleife
    				}
    		  var = atoi(tmp_string);								// Umwandlung in ein Integer
    		  if ( var < min || var > max )
    		  {
    		  	austritt2 = 0;
    		  	austritt = 0;
    		  }
    		  else
    		  	austritt2 = 1;
    		}
    
    	}
    	return var;
    }
    
    void new_screen(void)
    {
    	int count;
    	for (count=305;count>0;count--)
    	{
    		printf("\n");
    	}
    }
    
    double d_eingabe(double min, double max)
    {
    	int cnt;
    	int vorzeichen = 1;
    	double var = (max+1);
    	double tmp_var;
    	int is_zahl = 0;
    	int austritt = 0;
    	int austritt2 = 0;
    	int tmp_int;
    	int komma = 0;
    	unsigned int lange = 0;
    	char tmp_string[40+1];
    	char *zgr;
    
    while ( austritt2 == 0 )						// Legt Wertebereich fest
    {
    		while ( austritt == 0 )					
    		{	
    				printf("\0gabe ==> ");
    				fgets(tmp_string, (40+1), stdin);				// LIEßT STING EIN
    				komma = 0;
    				lange = strlen(tmp_string);					
    				for(cnt=0; cnt<(lange-1); cnt++)		// lange-1, weil wir '\0' nicht vergleichen wollen
    				{
    					tmp_int = tmp_string[cnt];
    					is_zahl = isdigit(tmp_int);
    					if ( is_zahl == 0 )								// Wenn keine Ziffer --> Schleife startet neu
    					{
    						if ( (tmp_int == '-') && (cnt == 0) )
    						{
    							vorzeichen = -1;
    							austritt = 1;
    						}
    						else if ( ((tmp_int != 44) && (tmp_int != 46)) || (komma != 0) )
    						{
    							austritt = 0;
    							break;
    						}
    						else
    						{
    							komma = 1;
    						}
    					}
    					else
    						austritt = 1;										// Wenn nur Ziffern --> Beendet Schleife
    				}
    		  var = vorzeichen * atoi(tmp_string);								// Umwandlung in ein Integer
    		  if ( komma == 1 )
    		  {
    		  	zgr = strchr(tmp_string, 44);
    			  if ( zgr == NULL )
    			  	zgr = strchr(tmp_string, 46);
    			  zgr++;
    			  tmp_var = atoi(zgr);
    			  while ( tmp_var > 1 )
    			  {
    			  	tmp_var /= 10;
    			  }
    			  var += tmp_var;
    			}
    		  if ( var < min || var > max )
    		  {
    		  	austritt2 = 0;
    		  	austritt = 0;
    		  }
    		  else
    		  	austritt2 = 1;
    		}
    
    }
    return var * vorzeichen;
    }
    #endif
    

    Viel Spaß damit.



  • Das ganze kann man natürlich noch verbessern.

    Man könnte direkt auf ungültige Eingaben prüfen und diese dann wiederholen.
    Ich weiß z.B. nicht ob das Programm für a = 0 funktionieren soll, weil es ja keine Parabell, sondern nur noch eine Gerade ist.
    Wenn a und b null sind müsste man auch noch eine Fehlermeldung einbauen, sowie bei ungültigen Grenzen.

    Außerdem ist der Wert ziemlich schlecht, wenn nur wenig Teilintervalle eingegeben wurde und das Integral über eine Nullstelle auf der X-Achse verläuft.

    Optimiert könnte man die Nullstellen auf der X-Achse errechnen und darauf je eine zusätzliche Höhen setzen und die beiden Teilflächen seperat addieren.



  • Simonek schrieb:

    int jn_frage(void)											// ÜBERSETZT J/N in 1/0
    {
    	char a = 'a';
    	char puf[20];
    	
    	while ( strchr( "NnJj", a ) == NULL )
    		{
    					fgets(puf, 20, stdin);
    					a = *puf;
    		}
    	
    		if (a == 'j' || a == 'J') {
    			return 1; 
    		}
    		else
    			return 0;
    }
    

    scheint mir sehr umständlich...
    warum nicht so ähnlich: ?

    int jn_frage (void)
    {
        try_again:
        switch (getchar() | 0x20)
        {
            case 'j':
            return 1;
    
            case 'n':
            return 0;
        }
        goto try_again;
    }
    

    🙂



  • Das goto benutzt du jetz absichtlich gell? 😉

    Lass das. Provoziers nicht immer.



  • TactX schrieb:

    Das goto benutzt du jetz absichtlich gell? 😉
    Lass das. Provoziers nicht immer.

    int jn_frage (void)
    {
        for(;;) switch (getchar() | 0x20)
        {
            case 'j':
            return 1;
    
            case 'n':
            return 0;
        }
    }
    

    so besser?



  • Für Verbesserungen bin ich immer dankbar 🙂
    Würde das heute wahrscheinlich auch nicht mehr so schreiben 😉

    Ich hab die ausführbare Datei mal hochgeladen:

    http://www.existence-online.de/hosted/Simonek/integral.exe RETAIL
    http://www.existence-online.de/hosted/Simonek/dintegral.exe DEBUG

    wenn Du Dir das compilen ersparen willst...



  • lass das system("cls") (clrscr() -> system("cls")) raus. is ja haesslich.



  • Wie gesagt ich bin immer für Verbesserungen dankbar.

    Ich wollte eine Funktion zum Bildschirm-Leeren, die auf möglichst vielen Systemen funktioniert.
    Was besseres wie system cls habe ich für die WIN32-Konsole bisher nicht gefunden, ohne irgendwelche APIs zu benutzen.



  • ihr seid krass!!! vielen vielen DANK!!!
    jetzt habt ihr doch meine Hausaufgaben gemacht 😉
    ich werde ma probieren das in mein programm zu übernehmen...
    danke nochma, besonders @ Simonek, für die Mühe

    mfg



  • tzuio schrieb:

    ihr seid krass!!! vielen vielen DANK!!!
    jetzt habt ihr doch meine Hausaufgaben gemacht 😉
    ich werde ma probieren das in mein programm zu übernehmen...
    danke nochma, besonders @ Simonek, für die Mühe

    mfg

    wer von euch hier geholfen hat und sich jetzt nicht schaemt, sollte sich wirklich schaemen.



  • ????????? NULL Toleranz für Anfänger ????????
    schaem dich



  • tzuio schrieb:

    ????????? NULL Toleranz für Anfänger ????????
    schaem dich

    Das hat mit Toleranz gegenüber Anfängern eigentlich nichts zu. Erklär mir bitte mal den Sinn von Hausaufgaben.



  • man sollte sie daheim erledigen.
    und aus eigener kraft. is klar
    wenn man jedoch ums verrecken nicht weiter kommt...
    sollte man eben auch wissen wie man sich helfen kann...recherche genannt...
    das ist meiner meinung nach die wichtigste erfahrung bei Hausaufgaben!

    hier ist mir geholfen worden, von leuten die ahnung haben!!!
    wo liegt dabei dein problem?



  • Nein, dir ist nicht wirklich geholfen worden. Dir wurde eine Lösung präsentiert. Du hast 0 Zeilen selbst hinbekommen und hast jetzt > 100 Zeilen "bekommen". Wenn du das unter "Recherche" verstehst... dann gute nacht 🙄



  • Jo, aber du hast nicht so viel dabei gelernt, als wenn dir nur Tipps und Hilfestellungen anstatt der komplette Quellcode gegeben worden wären. Das ist dein Problem.


Anmelden zum Antworten