Forum: PC-Programmierung Funktionen in C


von Leyla S. (keeke)


Lesenswert?

Hallo,

ich habe Probleme damit in C Funktionen aufzustellen.

Die Aufgabe lautet: Schreibe eine Funktion, die 3 float-Zahlen einliest.
Mit Hilfe zwei weiteren Funktionen soll die größte float-Zahl und der 
Durchschnittswert der Zahlen ausgegeben werden. Rufen Sie die Funktionen 
direkt aus der Parameterliste einer printf()-Anweisung als Parameter von 
printf() auf.
Die Funktionen sollen wie folgt benannt werden:
Maximalwert: float max()
Durchschnitt: float average()

Ich hoffe jemand kann mir hierbei Schritt für Schritt helfen. Es muss 
auch nicht diese Aufgabe sein. Mir geht es viel mehr um das Verständnis 
:)
Meine Ideen:
1
#include <stdio.h>
2
float max();//Deklaration
3
float average();
4
float einlesen();
5
int main(void)
6
{
7
    float einlesen();
8
    float average();
9
    float max();
10
    return 0;
11
12
}
13
float einlesen(){
14
            float zahl1, zahl2, zahl3;
15
            printf("Bitte geben Sie die erste Zahl ein:\n");
16
            scanf("%f", &zahl1);
17
            printf("Bitte geben Sie die zweite Zahl ein:\n");
18
            scanf("%f", &zahl2);
19
            printf("Bitte geben Sie die dritte Zahl ein:\n");
20
            scanf("%f", &zahl3);
21
            return 0;
22
23
float average(){
24
            printf("\nDurchschnittswert %f\n", (zahl1+zahl2+zahl3)/3);
25
}

von mic (Gast)


Lesenswert?

Mal ein Anfang:
1
#include <stdio.h>
2
float max(void);//Deklaration
3
float average(void);
4
float einlesen(void);
5
int main(void)
6
{
7
    einlesen();
8
    average();
9
    max();
10
    return 0;
11
12
}
13
float einlesen(void){
14
            float zahl1, zahl2, zahl3;
15
            printf("Bitte geben Sie die erste Zahl ein:\n");
16
            scanf("%f", &zahl1);
17
            printf("Bitte geben Sie die zweite Zahl ein:\n");
18
            scanf("%f", &zahl2);
19
            printf("Bitte geben Sie die dritte Zahl ein:\n");
20
            scanf("%f", &zahl3);
21
            return 0;
22
23
float average(void){
24
            printf("\nDurchschnittswert %f\n", (zahl1+zahl2+zahl3)/3);
25
}

Wie du die "zahl1", "zahl2" und "zahl3" aus der Funktion "einlesen" 
herausbekommst, überlasse ich dir.

von Leyla S. (keeke)


Lesenswert?

Danke schon mal. Also anstatt void die Übergabeparameter eintragen, wenn 
ich dich richtig verstanden habe?
1
#include <stdio.h>
2
float max(void);//Deklaration
3
float average(void);
4
float einlesen(void);
5
int main(void)
6
{
7
    einlesen();
8
    average();
9
    max();
10
    return 0;
11
12
}
13
float einlesen(float zahl1, float zahl2, float zahl3){
14
            float zahl1, zahl2, zahl3;
15
            printf("Bitte geben Sie die erste Zahl ein:\n");
16
            scanf("%f", &zahl1);
17
            printf("Bitte geben Sie die zweite Zahl ein:\n");
18
            scanf("%f", &zahl2);
19
            printf("Bitte geben Sie die dritte Zahl ein:\n");
20
            scanf("%f", &zahl3);
21
            return 0;
22
23
float average(float zahl1, float zahl2, float zahl3){
24
            printf("\nDurchschnittswert %f\n", (zahl1+zahl2+zahl3)/3);
25
}

von libba (Gast)


Lesenswert?

Ohweh, da fehlt einiges. Das Programm wird nie etwas sinnvolles 
ausgeben.
Du deklarierst Deine Variablen erst in der Funktion "einlesen". Das sind 
damit lokale Variablen. Was passiert mit lokalen Variablen, wenn die 
Funktion verlassen wird?

Du hast mehrere Möglichkeiten die Variablen nutzbar zu machen:

1. Globale Variablen, ist aber schlechter Stil und sollte vermieden 
werden
2. Pointer, wenn Ihr davon schon was gehört habt
3. Über Return-Wert

Außerdem wird keine der Funktionen so wie Du es geschrieben hast, als 
Parameter von printf() aufgerufen.

Überlege Dir:

Was ist eine Funktion?
Was ist ein Funktionsparameter?
Was ist printf()?

von mikeii (Gast)


Lesenswert?

Rufen Sie die Funktionen direkt aus der Parameterliste einer 
printf()-Anweisung als Parameter von printf() auf.

Im die Funktion average kommt kein printf! raus damit. Die soll den Wert 
doch berechnen.

von Leyla S. (keeke)


Lesenswert?

1
#include <stdio.h>
2
float max(void);//Deklaration
3
float average(void);
4
float einlesen(void);
5
int main(void)
6
{
7
    einlesen();
8
    average();
9
    max();
10
    return 0;
11
12
}
13
float einlesen(float zahl1, float zahl2, float zahl3){
14
            float zahl1, zahl2, zahl3;
15
            printf("Bitte geben Sie die erste Zahl ein:\n");
16
            scanf("%f", &zahl1);
17
            printf("Bitte geben Sie die zweite Zahl ein:\n");
18
            scanf("%f", &zahl2);
19
            printf("Bitte geben Sie die dritte Zahl ein:\n");
20
            scanf("%f", &zahl3);
21
            return 0;
22
23
float average(float zahl1, float zahl2, float zahl3){
24
            float a=0;
25
            a = (zahl1+zahl2+zahl3)/3;
26
}

Pointer hatten wir nocht nicht, also muss ich mit return arbeiten.
Habe printf jetzt entfernt.

von Matthias L. (Gast)


Lesenswert?

1
#include <stdio.h>
2
float max(void);//Deklaration
3
float average(void);
4
float einlesen(void);
5
int main(void)
6
{
7
    float zahl1 = einlesen();
8
    float zahl2 = einlesen();
9
    float zahl3 = einlesen();
10
    printf("\nDurchschnittswert %f\n", average(zahl1,zahl2,zahl3) );
11
    printf("\nDurchschnittswert %f\n", max    (zahl1,zahl2,zahl3) );
12
    return 0;
13
14
}
15
16
float einlesen(void)
17
{
18
            float zahl;
19
            printf("Bitte geben Sie eine Zahl ein:\n");
20
            scanf("%f", &zahl);
21
            return zahl;
22
}
23
24
float average(float zahl1, float zahl2, float zahl3)
25
{
26
    return ( (zahl1+zahl2+zahl3)/3);
27
}
28
29
Float max (float zahl1, float zahl2, float zahl3)
30
{
31
    Float max = 0;
32
    If ( max < zahl1)  max = zahl1;
33
    If ( max < zahl2)  max = zahl2;
34
    If ( max < zahl3)  max = zahl3;
35
    Return max;
36
}

von DirkB (Gast)


Lesenswert?

Matthias Lipinsky schrieb:
> Float max (float zahl1, float zahl2, float zahl3)
> {
>     Float max = 0;
>     If ( max < zahl1)  max = zahl1;
>     If ( max < zahl2)  max = zahl2;
>     If ( max < zahl3)  max = zahl3;
>     Return max;
> }

Und bei negativen Zahlen ist dann 0 das Maximum.

Darum erstmal dem max den ersten Wert zuweisen:
1
    float max = 0;
2
    if ( max < zahl2)  max = zahl2;
3
    if ( max < zahl3)  max = zahl3;
4
    return max;


Leyla S. schrieb:
> Pointer hatten wir nocht nicht, also muss ich mit return arbeiten.

Und was machst du bei scanf?

von Leyla S. (keeke)


Lesenswert?

Danke. Habe mal Kommentare geschrieben, kann die jemand mal bitte 
überprüfen?
1
#include <stdio.h>
2
float max(void);//Deklaration
3
float average(void);
4
float einlesen(void);
5
int main(void)//main Funktion gibt die Ergebnisse aus
6
{
7
    float zahl1 = einlesen();
8
    float zahl2 = einlesen();
9
    float zahl3 = einlesen();
10
    printf("\nDurchschnittswert %f\n", average(zahl1,zahl2,zahl3) );
11
    printf("\nDurchschnittswert %f\n", max    (zahl1,zahl2,zahl3) );
12
    return 0;
13
14
}
15
16
float einlesen(void)
17
{
18
            float zahl;//Wieso wird hier nur eine Zahl eingelesen?
19
            printf("Bitte geben Sie eine Zahl ein:\n");
20
            scanf("%f", &zahl);
21
            return zahl;
22
}
23
24
float average(float zahl1, float zahl2, float zahl3)
25
{
26
    return ( (zahl1+zahl2+zahl3)/3);/*der Wert wird an die main Funktion übergeben*/
27
}
28
29
float max (float zahl1, float zahl2, float zahl3)
30
{
31
    float max = 0;
32
    if ( max < zahl1)  max = zahl1;
33
    if ( max < zahl2)  max = zahl2;
34
    if ( max < zahl3)  max = zahl3;
35
    return max; //max wird an main übergeben
36
}

von Leyla S. (keeke)


Lesenswert?

Bei scanf wird einem Datentyp die Adresse zugewiesen, aber wie gesagt 
Pointer höre ich zum ersten Mal.

von libba (Gast)


Lesenswert?

Sehr schön. Damit wurde Dein Problem extern gelöst. Da Du aber Deinem 
Lehrer/Professor/Wasauchimmer das Programm erklären müssen wirst, 
solltest Du trotzdem versuchen Dir über die Fragen, die ich gestellt 
habe, Gedanken zu machen.

Dazu kommt, dass Du, wenn Du die Lösung von Lippy nehmen möchtest, Dir 
überlegen musst, was der Unterschied zwischen

if und If

sowie zwischen

float und Float ist.

Die obige Lösung wird sich nicht kompilieren lassen.

von libba (Gast)


Lesenswert?

Die Antwort bezog sich auf Lippys Quellcode. Die Fehler hast Du schon 
bereinigt.

Bei "einlesen" wird nur eine Zahl eingelesen, dafür aber die Funktion 
dreimal aufgerufen. Mit dem return-Wert weist Du den Variablen ihren 
Wert zu.

von Matthias L. (Gast)


Lesenswert?

>float und Float ist.

Das ist die pseudointelligenz vom tablett.

>Und bei negativen Zahlen ist dann 0 das Maximum

Das kann er dann selbst korrigieren.

von Leyla S. (keeke)


Lesenswert?

Ja ich versuche die Lösung grad zu verstehen.
Ich weiß, dass Funktionen kleine Unterprogramme der Hauptfunktionen main 
sind. Die Parameter sind die Übergabewerte.
Mit printf wird etwas ausgegeben. Und das c case sensitive ist, ist mir 
bewusst.
Aber das Programm konnte ich trotzdem nicht kompilieren.

von Matthias L. (Gast)


Lesenswert?

Die funktionsprototypen vor dem main stimmen nicht mit denennach dem 
Main überein. Entweder anpassen oder die Prototypen löschen und die 
hilfsfunktionen vor das main schreiben

von Leyla S. (keeke)


Lesenswert?

Ok nochmal zum Einlesen, wo sehe ich, dass die Funktion dreimal 
aufgerufen wird? Liegt es hier an dem Code-Fragment:
1
float zahl1 = einlesen();
2
    float zahl2 = einlesen();
3
    float zahl3 = einlesen();

von Leyla S. (keeke)


Lesenswert?

1
#include <stdio.h>
2
float max(float zahl1,float zahl2, float zahl3);//Deklaration
3
float average(float zahl1, float zahl2, float zahl3);
4
float einlesen();
5
int main(void)
6
{
7
    float zahl1 = einlesen();
8
    float zahl2 = einlesen();
9
    float zahl3 = einlesen();
10
    printf("\nDurchschnittswert %f\n", average(zahl1,zahl2,zahl3) );
11
    printf("\ngrößte Zahl %f\n", max    (zahl1,zahl2,zahl3) );
12
    return 0;
13
14
}
15
16
float einlesen()
17
{
18
            float zahl;
19
            printf("Bitte geben Sie eine Zahl ein:\n");
20
            scanf("%f", &zahl);
21
            return zahl;
22
}
23
24
float average(float zahl1, float zahl2, float zahl3)
25
{
26
    return ( (zahl1+zahl2+zahl3)/3);
27
}
28
29
float max (float zahl1, float zahl2, float zahl3)
30
{
31
     float max = 0;
32
    if ( max < zahl2)  max = zahl2;
33
    if ( max < zahl3)  max = zahl3;
34
    return max;
35
}

von libba (Gast)


Lesenswert?

> Mit printf wird etwas ausgegeben.

Worauf ich hinaus wollte: printf() ist genauso eine Funktion wie es 
Deine average-Funktion auch ist. Sie hat genauso Übergabeparameter wie 
die anderen Funktionen. Du sollst dort halt als Übergabeparameter die 
average-Funktion statt einer Variablen nutzen. Da aber die 
Average-Funktion den Wert einer Variablen als return an die 
printf-Funktion übergibt, ist es, als wenn dort eine Variable stehen 
würde.

von libba (Gast)


Lesenswert?

Leyla S. schrieb:
> Ok nochmal zum Einlesen, wo sehe ich, dass die Funktion dreimal
> aufgerufen wird? Liegt es hier an dem Code-Fragment:
> float zahl1 = einlesen();
>     float zahl2 = einlesen();
>     float zahl3 = einlesen();

Ja. Die Funktion wird doch dreimal aufgerufen, dreimal wird damit der 
return-Wert an jeweils unterschiedliche Variablen übergeben.

von Leyla S. (keeke)


Lesenswert?

Ah okey. Erstmal vielen Dank an alle :)
Und noch eine Frage bei meinem ersten Post hatte ich in main nur
1
einlesen()
Mal abgesehen davon, dass ich keine Zuweisung hatte.

Muss immer ein Datentyp angegeben werden?

1
float zahl1 = einlesen();

von libba (Gast)


Lesenswert?

Gibst Du denn bei der printf-Funktion einen Datentyp an?

Einen Datentyp benötigst Du nur, wenn Du einen return-Wert erwartest.

Was ist der Unterschied zwischen void bla() und int blub()?

von Matthias L. (Gast)


Lesenswert?

>Muss immer ein Datentyp angegeben werden?

Nein.

Wenn Du nichts zurückgeben willst, gehts auch so.
1
main...
2
{
3
  ...
4
  function_ohne_return( ... );
5
  ...
6
}
7
8
void function_ohne_return( ... )
9
{
10
...
11
}

von Leyla S. (keeke)


Lesenswert?

Okey danke euch :)
void bla()--> parameterlos und
int blub()--> Datentyp ist int

von libba (Gast)


Lesenswert?

Fast richtig.

void bla() -> Du erwartest keinen return-Wert

int blub() -> Du erwartest einen return-Wert vom Typ int

von Matthias L. (Gast)


Lesenswert?

1
main
2
{
3
  bla();               // geht nur so
4
5
  blub();              // Return-Wert wird ignoriert
6
7
  int Zahl = blub();   // Return-wert wird verwendet
8
9
  ..
10
}

von Leyla S. (keeke)


Lesenswert?

So und da wäre noch eine Sache mit der ich auch schon angefangen habe. 
Und zwar soll diese Aufgabe in eine Menü untergebracht werden. Menü soll 
hierbei auch eine Funktion darstellen. Das müsste ich ja jetzt 
hinkriegen, aber mir habe scheinbar einen Fehler in der Deklaration.
1
#include <stdio.h>
2
int menue();
3
int aufgabe2();
4
float max(float zahl1,float zahl2, float zahl3);
5
float average(float zahl1, float zahl2, float zahl3);
6
float einlesen();
7
8
int main(){
9
int aufgabe;
10
menue();
11
return 0;
12
}
13
int menue(int aufgabe){
14
    printf("Aufgabe waehlen:\n (2) Aufgabe 2\n (3) Aufgabe 3\n (0) Programm Beenden");
15
    scanf("%d", &aufgabe);
16
    switch(aufgabe){
17
        case 2: printf("Aufgabe 2\n");
18
                break;
19
        case 3: printf("Aufgabe 3\n");
20
                break;
21
        case 0: printf("Programm beenden 0\n");
22
                break;
23
}
24
25
int aufgabe2(){
26
    float einlesen()
27
{
28
            float zahl;
29
            printf("Bitte geben Sie eine Zahl ein:\n");
30
            scanf("%f", &zahl);
31
            printf("\n%f ist die groesste eingelesene Kommazahl\n", max(zahl1, zahl2, zahl3));
32
            printf("Durchschnittswert = %f\n\n", average(zahl1, zahl2, zahl3));
33
            return zahl;
34
}
35
36
float average(float zahl1, float zahl2, float zahl3)
37
{
38
    return ( (zahl1+zahl2+zahl3)/3);
39
}
40
41
float max (float zahl1, float zahl2, float zahl3)
42
{
43
     float max = 0;
44
    if ( max < zahl2)  max = zahl2;
45
    if ( max < zahl3)  max = zahl3;
46
    return max;
47
}
48
}

von libba (Gast)


Lesenswert?

Du musst die Aufgaben, also die einzenlen Funktionen, auch aufrufen.

Und im switch/case fehlt eine Klammer.

von Karl H. (kbuchegg)


Lesenswert?

Leyla S. schrieb:

Wenn ich mir das so durchlese, denke ich der Fisch fängt hier zum 
stinken an:

> Muss immer ein Datentyp angegeben werden?
>
>
>
1
float zahl1 = einlesen();

Du hast nicht begriffen, dass hier 2 Dinge passieren.

Zum einen wird eine Variable defniniert
1
  int i;
2
  int j;
3
  float zahl;

Das ist die Definition einer variablen wie jeder andere auch.

Und einer Variablen kann man bei der Definition einen Initialwert 
mitgeben.
1
  int i = 5;
2
  int j = 8;
3
  int zahl = 3.141592654;

soweit so gut.
Das andere ist ein Funktionsaufruf
1
  einlesen();

wird der Name einer Funktion mit einem () verwendet (und gegebenenfalls 
Argumente an die Funktion übergeben, die dann in den Klammern stehen), 
dann wird die Funktion aufgerufen und macht ihr Ding.
Jetzt gibt es aber Funktionen, die einen Wert berechnen. Zum Beispiel 
Sinus oder auch die Wurzel. Rufst du die Funktion auf, dann gibts du ihr 
den Wert mit, ....
1
    sqrt( 8 );
... die Funktion macht ihr Ding und liefert einen Wert. Nur: Du musst 
mit dem Wert auch etwas machen! Denn sonst ist es recht sinnlos eine 
Funktion aufzurufen, die irgendwas berechnet, wenn mit dem Berechneten 
nichts geschieht.
Der Wert, den die Funktion liefert, das ist ein Wert wie jeder andere. 
Er kann zb in Ausdrücken weiterverwendet werden
1
    3 * sqrt( 8 );
und genauso wie dieser Ausdruck einen neuen Wert berechnet und zur 
Verfügung stellt, den man dann an eine Variable zuweisen kann
1
   k = 3 * sqrt( 8 );
genauso kannst du auch einfach den Wert den die Funktion liefert an eine 
Variable zuweisen
1
   k = sqrt( 8 );
Rechts vom = steht ein arithmetischer Ausdruck. So ein Ausdruck setzt 
sich zusammen aus Konstanten
1
    5
aus Operation, die mit Konstanten gemacht werden
1
    5 + 3
oder den Werten, die in Variablen stehen
1
     k
1
    5 + k
oder eben auch den Werten, die von Funktionen zugeliefert werden
1
    5 + sqrt( 12 )
Aber auch die Werte, die an eine Funktion gehen, sind (in diesem Fall) 
einfach nur arithmetische Ausdrücke
1
    5 + sqrt( 3 * j )
Jeder Bestandteil, der vertreten ist, liefert einfach nur einen Wert, wo 
auch immer der herkommt. Konstanten stehen für sich selbst als Wert, bei 
Variablen ist ihr Inhalt gemeint und bei Funktionsaufrufen ist eben der 
Wert, den die Funktion zuliefert. Und mit den arithmetischen Operationen 
werden diese Werte verknüpft, wird also wieder ein weiterer Wert 
errechnet, bis dann auf der rechten Seite von
1
   k = .....
ein einziger Wert entstanden ist und der wird dann der Variablen 
zugewiesen.

Was hat das jetzt mit dem am Anfang über Variablen Definitionen zbw. 
Initialisierungen Gesagten zu tun?
Nun ganz einfach.
Hier
1
   float zahl = 3.141592654;
steht nur deshalb einen Zahlenkonstante, weil ich da eine hingeschrieben 
habe. Es könnte aber genausogut irgendein anderer arithmetischer 
Ausdruck sein ...
1
   float zahl = ( 3 + 2 ) * 5;
... der natürlich genausogut den Aufruf einer Funktion beinhalten kann, 
die einen Wert liefert.
1
  float zahl = sqrt( 5 );

Hier, in der letzten Zeile, sind also einfach nur ein paar Dinge 
zusammengeführt und gemeinsam in einer einzigen Zeile benutzt worden! 
Mehr steckt da nicht dahinter.

Wenn es mir nicht so wichtig ist, das Ganze als Initialisierung zu 
sehen, kann ich das selbstverständlich auch so schreiben
1
   float zahl;
2
3
   zahl = sqrt( 5 );
Dann hat eben die Variable Zahl, wenn sie zur Welt kommt, keinn 
eindeutig definierten Wert, sondern kriegt ihn erst, wenn ihr der Wert 
aus dem Funktionsaufruf zugewiesen wird.

Wie schreibt man nun eine Funktion, die einen Wert liefert? Wie muss 
sqrt, also die Wurzelfunktion, aussehen, damit sie genau das kann: Einen 
Wert übernehmen und einen Wert liefern.
So
1
float sqrt( float zahl )
2
{
3
  float ergebnis;
4
5
  ....
6
  // mach dein Ding zur Berechnnung der Wurzel von 'zahl'
7
  // das Resultat dieses Dings soll in der lokalen Variablen 'ergebnis'
8
  // vorliegen
9
10
  return ergebnis;
11
}

Das erste float, das vor dem Funktionsnamen, bezeichnet den Datentyp des 
Ergebnisses. Innerhalb der Funktion gibt es eine lokale Variable, in der 
die Berechnung gemacht wird. Am Ende der Funktion, wenn das korrekte 
Ergebnis in 'ergebnis' vorliegt, kommt der 'return' zur Ausführung. Und 
beim return gebe ich einen Ausdruck an, der den Wert bestimmt, welcher 
als Rückgabewert der Funktion dienen soll. D.h. hier wird dann der Wert 
auf die Reise geschickt, der beim Aufrufer
1
  float zahl = sqrt( 12 );
dann wieder auftaucht und in diesem Fall zur Initialisierung der 
Variablen dient. Wie gesagt: das muss keine Intialisierung sein. Ich 
kann mit dem Wert, den ich bekomme, machen was ich will. Zb in einer 
Berechnung verwenden
1
  hjk = 5 * sqrt( 8 );
oder ich kann diesen Wert zum Beispiel auch dazu benutzen, dass ich ihn 
an eine andere Funktion als Argument übergebe, die dann ihrerseits mit 
dem so erhaltenen Wert wieder was berechnet
1
   j = sin( sqrt( 3 ) );
Das kann auch wieder die Funktion selber sein
1
  j = sqrt( sqrt( 4 ) ),

das ist alles an dieser Stelle nicht wirklich wichtig. Wichtig ist, dass 
diese Funktion sqrt einen Wert übernimmt und einen Wert liefert. Wo der 
Wert herkommt, den die Funktion übernimmt, ist nicht das Bier der 
Funktion, die kriegt einfach nur den ausgerechneten Wert als Argument 
mit
1
   j = sqrt( 3 * 4 + 8 );
bzw. sie liefert einen Wert, mit dem ich dann weiterarbeite.

Wenn es in Funktionen reingeht, dann bist du in deiner Ausbildung so 
weit, dass du erkennen musst, das es nicht für alles und jedes ein 
Kochrezept gibt, dem du nur folgen musst. Es beginnt jetzt immer mehr 
die Phase, in der du anfängst, die bisher gelernten Basisdinge 
miteinander zu kombinieren. Dazu musst du diese Basisdinge aber auch 
erkennen können und musst sie kennen! Und ja. Das ist eines der Dinge, 
die in Programmiersprachen das Um und Auf darstellen: 
Programmiersprachen sind deswegen mächtig, weil man Konzepte miteinander 
kombinieren kann. Das ist wie beim Schach-Spiel: Wie die Figuren ziehen 
können, das lernt man in 2 Stunden. Aber wie man aus der Kombination 
dieser Möglichkeiten sein Spiel so anlegt, dass man gewinnt, daran lernt 
man ein Leben lang. Nichts desto trotz, ist aber die Kenntnis der 
Zugmöglichkeiten die Grundlage für alles weitere. Wenn du also in den 
bisherigen Unterrichtseinheiten nicht aufgepasst hast, weil das ja eh 
alles pipi-einfach ist bzw. die Übungen nicht selbst gemacht hast, dann 
solltest du das Versäumte schleunigst nachholen. Denn das sind die 
Grundlagen, auf denen alles weitere aufbaut. Beherrscht du die nicht, 
dann überrollt dich alles weitere, ohne das du eine Chance hast, dagegen 
etwas zu tun.

: Bearbeitet durch User
von Leyla S. (keeke)


Lesenswert?

Vielen Dank für die ausführliche Antwort. Habe jetzt noch eine Sache im 
Programm umgeändert, undzwar habe ich in case 2 einlesen() drinstehen 
(und int aufgabe2() entfernt),dies müsste doch jetzt die Funktion float 
einlesen aufrufen? Innerhalb der Funktion float einlesen() erwartet die 
Funktion printf den Wert max, also müsste doch auf die entsprechende 
Funktion, weiter unten zugegriffen werden? Was aber wohl hier nicht der 
Fall ist.
1
#include <stdio.h>
2
int menue();
3
int aufgabe2();
4
float max(float zahl1,float zahl2, float zahl3);
5
float average(float zahl1, float zahl2, float zahl3);
6
float einlesen();
7
8
int main(){
9
int aufgabe;
10
menue();
11
return 0;
12
}
13
int menue(int aufgabe){
14
    printf("Aufgabe waehlen:\n (2) Aufgabe 2\n (3) Aufgabe 3\n (0) Programm Beenden");
15
    scanf("%d", &aufgabe);
16
    switch(aufgabe){
17
        case 2: printf("Aufgabe 2\n");
18
                einlesen();
19
                break;
20
        case 3: printf("Aufgabe 3\n");
21
                break;
22
        case 0: printf("Programm beenden 0\n");
23
                break;
24
}
25
}
26
27
float einlesen(float zahl1, float zahl2, float zahl3)
28
{
29
            float zahl;
30
            printf("Bitte geben Sie eine Zahl ein:\n");
31
            scanf("%f", &zahl);
32
            printf("\n%f ist die groesste eingelesene Kommazahl\n", max(zahl1, zahl2, zahl3));
33
            printf("Durchschnittswert = %f\n\n", average(zahl1, zahl2, zahl3));
34
            return zahl;
35
}
36
37
float average(float zahl1, float zahl2, float zahl3)
38
{
39
    return ( (zahl1+zahl2+zahl3)/3);
40
}
41
42
float max (float zahl1, float zahl2, float zahl3)
43
{
44
     float max = 0;
45
    if ( max < zahl2)  max = zahl2;
46
    if ( max < zahl3)  max = zahl3;
47
    return max;
48
}
49
}

von mic (Gast)


Lesenswert?

Leyla S. schrieb:
> float max = 0;

Das muss heißen:

float max = zahl1;

Sonst kommt vermutlich nicht das dabei heraus was du wolltest.

von libba (Gast)


Lesenswert?

Leyla, das mag jetzt etwas hart klingen, aber Du hast nichts von dem 
verstanden, was wir Dir, insbesondere Karl-Heinz, versucht haben, zu 
erklären. Du wirst große Probleme bekommen, wenn Du das Programm Deinem 
Lehrer vorstellen musst.

Leyla S. schrieb:
1
> 
2
> float einlesen(float zahl1, float zahl2, float zahl3)
3
> {
4
>             float zahl;
5
>             printf("Bitte geben Sie eine Zahl ein:\n");
6
>             scanf("%f", &zahl);
7
>             printf("\n%f ist die groesste eingelesene Kommazahl\n", 
8
> max(zahl1, zahl2, zahl3));
9
>             printf("Durchschnittswert = %f\n\n", average(zahl1, zahl2, 
10
> zahl3));
11
>             return zahl;
12
> }

wo sollen denn zahl1, zahl2, zahl3, die Du der Funktion einlesen als 
Parameter übergibst, denn herkommen? Welche Berechnungen führst Du mit 
zahl durch?

Was in Deinem Programm passiert:
1
> float einlesen(float zahl1, float zahl2, float zahl3)
Du rufst eine Funktion auf und übergibst ihr drei Variablen, die zuvor 
nirgends auftauchten. Sollte sich das so kompilieren lassen, sind die 
Werte der drei Zahlen zufällig. Kann irgendwas sein.

1
>             float zahl;
2
>             printf("Bitte geben Sie eine Zahl ein:\n");
3
>             scanf("%f", &zahl);
Du deklarierst eine Variable zahl und weist ihr mit scanf einen Wert zu. 
Eine Variable, ein Wert!

1
>             printf("\n%f ist die groesste eingelesene Kommazahl\n", 
2
> max(zahl1, zahl2, zahl3));
Du rufst eine Funktion max() auf, übergibst ihr die drei Variablen aus 
den Parametern, deren Werte immer noch zufällig sind. Aus diesen drei 
Werten wird der größte Wert ermittelt (oder besser sollte, denn in der 
Funktion max() ist auch noch ein Fehler). Doch da die Werte der 
Variablen zufällig sind, ist auch das Ergebnis zufällig. Dieser 
zufällige Wert wird an die Funktion printf() übergeben und ausgegeben.

1
>             printf("Durchschnittswert = %f\n\n", average(zahl1, zahl2, 
2
> zahl3));
Hier passiert dasselbe, wie eben beschrieben. Drei zufällige Werte in 
den Variablen, zufälliges Ergebnis.

1
>             return zahl;
Hier gibst Du den Wert, den Du zuvor mit scanf() eingelesen hast, 
unverändert an die aufrufende Funktion menue() zurück. Dort wird, da der 
Wert in der Funktion menue() keiner weiteren Variablen zugewiesen wird, 
der Wert einfach verworfen. Aber was sollte sie auch mit dem Wert.

Ich hoffe, Du erkennst, dass Du einiges nochmal nachlesen solltest. 
Selbst wenn ich Dir die Lösung hier hinschreibe, hilft Dir das nichts, 
denn die Fehler, die Du machst, sind so grundlegend, dass sie bei jeder 
weiteren Aufgabe wieder auftauchen.

Wenn Du verstanden hast, warum Deine Funktion einlesen() nicht 
funktionieren kann, dann bist Du auch in der Lage, den Fehler in der 
Funktion max() selbst zu finden und zu eliminieren.

von Leyla S. (keeke)


Lesenswert?

@libba da hast du recht im Endeffekt bringen mir die Lösungen nichts. 
Die Aufgabe werde ich nicht vorstellen, dafür war sie nicht gedacht. 
Vielmehr versuche ich das Thema mit den Funktionen zu verstehen, aber 
habe momentan ziemlich viele Schwierigkeiten damit.  Ich werde mich 
gleich auch dransetzen und nochmal alles dazu durchlesen und versuchen 
alles nachzuvollziehen, auch was Karl geschrieben hat.
Also auf jeden Fall vielen Dank nochmal für eure Hilfe.
Hat jemand zufällig Buch Empfehlungen?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Leyla S. schrieb:
> Hat jemand zufällig Buch Empfehlungen?

Ja.
Brian Kernighan & Dennis Ritchie, "Programmieren in C", zweite Ausgabe, 
Hanser-Verlag.

Das ist zwar schon recht alt, beschreibt aber nach wie vor die 
relevanten Grundzüge des Programmierens in C.

Zwar sind mittlerweile Erweiterungen des C-Sprachstandards 
hinzugekommen, die auch ihre Daseinsberechtigung haben, aber nichts von 
dem, was 1989 korrekt war, ist jetzt falsch. Jetzt geht nur manches auf 
noch andere Art und Weise.

Für Deine Probleme aber ist das nicht von Belang, die Konzepte "Was ist 
eine Variable", "Was ist die 'Sichtbarkeit' und was die 'Gültigkeit' 
einer Variablen" und "Wie werden Variablen an Funktionen übergeben" sind 
unveränderte Klassiker.

von Leyla S. (keeke)


Lesenswert?

Das hat zwar jetzt ziemlich lange gedauert, aber besser spät als nie.
Ist es so richtig bzw erlaubt, float zahl1, zahl2, zahl3 unter case zu 
deklarieren, so wie ich es gemacht habe?

1
#include <stdio.h>
2
int menue(int aufgabe);
3
float max(float zahl1,float zahl2, float zahl3);
4
float average(float zahl1, float zahl2, float zahl3);
5
float einlesen(float zahl1, float zahl2, float zahl3);
6
int main(){
7
int aufgabe;
8
menue(aufgabe);
9
return 0;
10
}
11
int menue(int aufgabe){
12
13
  do{
14
    printf("\nAufgabe waehlen: \n\n");
15
    printf("(2) Aufgabe 2\n");
16
    printf("(0) Programm Beenden\n\n");
17
                scanf("%d", &aufgabe);
18
19
  switch(aufgabe){
20
21
      case 2:
22
      printf("Aufgabe 2\n\n");
23
      float zahl1,zahl2,zahl3;
24
      einlesen(zahl1,zahl2,zahl3);
25
      break;
26
      case 0:
27
      printf("Programm beendet!\n");
28
      break;
29
      default:
30
      printf("Falsche Eingabe\n");
31
      }
32
  }while(aufgabe != 0);
33
34
  return 0;
35
  }
36
37
38
39
float einlesen(float zahl1, float zahl2, float zahl3) {
40
41
  printf("\n");
42
43
  printf("Bitte 1. Kommazahl eingeben: ");
44
  scanf("%f", &zahl1);
45
46
  printf("Bitte 2. Kommazahl eingeben: ");
47
  scanf("%f", &zahl2);
48
49
  printf("Bitte 3. Kommazahl eingeben: ");
50
  scanf("%f", &zahl3);
51
  printf("\n%f ist die groesste eingelesene Kommazahl\n", max(zahl1, zahl2, zahl3));
52
  printf("Durchschnittswert = %f\n\n", average(zahl1, zahl2, zahl3));
53
54
  return 0;
55
}
56
57
float average(float zahl1, float zahl2, float zahl3)
58
{
59
    return ( (zahl1+zahl2+zahl3)/3);
60
}
61
62
float max (float zahl1, float zahl2, float zahl3)
63
{
64
     float max = zahl1;
65
    if ( max < zahl2)
66
            max = zahl2;
67
    if ( max < zahl3)
68
            max = zahl3;
69
    return max;
70
}

von Karl H. (kbuchegg)


Lesenswert?

Leyla S. schrieb:
> Das hat zwar jetzt ziemlich lange gedauert, aber besser spät als nie.
> Ist es so richtig bzw erlaubt, float zahl1, zahl2, zahl3 unter case zu
> deklarieren,

das kannst du ganz leicht feststellen, in dem du es durch den Compiler 
jagst. Wenn der Compiler nichts dazu zu sagen hat, dann ist es zumindest 
syntaktisch schon mal nicht falsch ....

> so wie ich es gemacht habe?

... was allerdings nicht heisst, dass es auch von der Bedeutung her 
korrekt ist.

"Das Flugzeug strickt die Fischstäbchen."
ist ein nach Duden korrekter Satz. Er erfüllt alle 
Grammatikanforderungen, alle Wörter sind definiert, der Satzbau ist 
korrekt und auch alle Wortformen stimmen.
Trotzdem ist er Unsinn.

Das eine ist die Syntax. Also die Grammatikregeln einer 
Programmiersprache.
Das andere ist die Semantik. Also die Bedeutung, die ein bestimmtes 
Konstrukt hat. Da verwechselst hier die beiden Dinge bzw. gehst davon 
aus, dass du ein sinnvolles korrektes Programm hast, wenn du die 
Sprachregeln eingehalten hast. Dem ist aber nicht so.

: Bearbeitet durch User
von Christopher (Gast)


Lesenswert?

Welche Hilfsmittel verwendest du eigentlich?
Wurde dir ein Buch empfohlen oder gibt es ein Skript oder alles nur 
mündlich?

Wie testest du, ob das was du machst funktioniert? Dann wirst du ja 
sehen, wie sich dein Programm verhält. Wenn du dann noch einfach einen 
Schrittbetrieb mit einem debugger machst, dann kannst du Fehler selbst 
finden und beheben.

Es gibt grundlegende Einführungsbeispiele zu C im Internet (über google 
und Co zu finden).

Das war jetzt bewusst nicht konstruktiv. Bitte erst mal die Grundlagen 
erarbeiten und dann an die Aufgabe. Die Aufgabenstellung klingt so, als 
wenn genau das gefordert wird. Etwas Zeit investieren und sich die 
Sachen Stück für Stück aneignen. Dann macht es auch Spass.

von Karl H. (kbuchegg)


Lesenswert?

Matthias hat dir hier
Beitrag "Re: Funktionen in C"
die Eingabefunktion auf eine Variante gearbeitet, die nur 1 Wert 
einliest. Und er tat das aus einem guten Grund! Offenbar habt ihr noch 
nicht gelernt, wie man eine Funktion schreibt, die ihre Ergebnisse über 
die Argumentschnittstelle zurück liefert. Entweder das, oder du hast es 
verschwitzt, wie das geht.

So
1
      einlesen(zahl1,zahl2,zahl3);
2
...
3
4
float einlesen(float zahl1, float zahl2, float zahl3) {
5
...

funktioniert das nicht. Hier müsste man mit Pointern arbeiten, damit dir 
Funktion in der Lage ist, die Variablen zahl1, zahl2 und zahl3 des 
Aufrufers zu verändern.

Allerdinfs erhebt sich auch die Frage, wozu die Funktion überhaupt diese 
Argumente benötigt. Denn sie braucht diese Argumente nicht, weil sie 
sowieso alles selber erledigt. Das könnte man genausogut auch mit 
lokalen Variablen erledigen
1
void einlesen() {
2
3
  float zahl1, zahl2, zahl3;
4
5
  printf("\n");
6
7
  printf("Bitte 1. Kommazahl eingeben: ");
8
  scanf("%f", &zahl1);
9
10
  printf("Bitte 2. Kommazahl eingeben: ");
11
  scanf("%f", &zahl2);
12
13
  printf("Bitte 3. Kommazahl eingeben: ");
14
  scanf("%f", &zahl3);
15
  printf("\n%f ist die groesste eingelesene Kommazahl\n", max(zahl1, zahl2, zahl3));
16
  printf("Durchschnittswert = %f\n\n", average(zahl1, zahl2, zahl3));
17
}

wodurch sich die ganze Fragestellung, ob du hier Variablen definieren 
kannst
1
      case 2:
2
      printf("Aufgabe 2\n\n");
3
      float zahl1,zahl2,zahl3;
4
      einlesen(zahl1,zahl2,zahl3);
5
      break;
überhaupt nicht mehr stellt. Denn der Funktionsaufruf benötigt ja keine 
Argumente mehr. Wodurch ein einfaches
1
      case 2:
2
      printf("Aufgabe 2\n\n");
3
      einlesen();
4
      break;
im Grunde schon reicht, wenn man die Aufgabenstellung aus dem 
Eröffnungsposting etwas wohlwollend auslegt.

von C-... (Gast)


Lesenswert?

Sieht schon mal deutlich besser aus, wen du es jetzt noch deinem 
Professor erklären kannst, bist du ein gutes Stück voran gekommen.

von Leyla S. (keeke)


Lesenswert?

Karl Heinz schrieb:
> Matthias hat dir hier
> Beitrag "Re: Funktionen in C"
> die Eingabefunktion auf eine Variante gearbeitet, die nur 1 Wert
> einliest. Und er tat das aus einem guten Grund! Offenbar habt ihr noch
> nicht gelernt, wie man eine Funktion schreibt, die ihre Ergebnisse über
> die Argumentschnittstelle zurück liefert. Entweder das, oder du hast es
> verschwitzt, wie das geht.

Also ich habe das schon verstanden, aber wusste nicht wie ich den ganzen 
Part in main hier auf diesen Fall umschreibe. Da in meiner main Funktion 
nur die aufgabe stehen darf. Ich hoffe du verstehst wo mein Problem 
liegt bzw. was ich meine.
Zum Zweiten das mit void einlesen() als Funktion verstehe ich besser.

Christopher schrieb:
> Welche Hilfsmittel verwendest du eigentlich?
> Wurde dir ein Buch empfohlen oder gibt es ein Skript oder alles nur
> mündlich?
C Galileo Openbook gibt's online und Programmieren in C, ich habe mir 
auch die jeweiligen Sachen dazu durchgelesen. Ja mit dem Debugger sehe 
ich meine Fehler, hier wurden mir keine angezeigt. Deswegen wollte ich 
nochmal im Forum fragen, weil ich mir eben an dieser einen Stelle 
unsicher war.

von Matthias L. (Gast)


Lesenswert?

Kleiner Vorschlag von mir:
Hier:
1
switch(aufgabe){
2
    case 2:
3
    printf("Aufgabe 2\n\n");
4
    float zahl1,zahl2,zahl3;
5
    einlesen(zahl1,zahl2,zahl3);
6
    break;
7
    case 0:
8
    ...

würde ich selbst lieber Klammern setzen:
1
switch(aufgabe)
2
{
3
  case 2:
4
  {  
5
    printf("Aufgabe 2\n\n");
6
    float zahl1,zahl2,zahl3;
7
    einlesen(zahl1,zahl2,zahl3);
8
    break;
9
  }
10
  case 0:
11
  {
12
    ...
13
  }
14
}


Aber das ist wohl Geschmackssache...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.