C (array aus Unterprogramm in Main zurück geben)

mindtrip_1

Grünschnabel
Zuerst möchte ich mich Entschuldigen das ich mein komplettes Programm hier so hinzugefügt habe. Kenne mich nicht mit der Seite aus da ich mich erst Heute angemeldet habe da ich Hilfe brauche und nichts verständliches im Internet gefunden habe.
Ich habe vor kurzem mit meinem Techniker angefangen und habe direkt so ein Ding vor die Füße geworfen bekommen. Habe mich mal dran getraut und bin zu dem Stand unten gekommen.

Mein Problem ist [Warning] comparison between pointer and integer [enabled by default]
Möchte aus denn Jeweiligen Rechnungen meines Unterprogrammes das Ergebnis an Main zurück geben, hänge seit 3 Tagen daran und komme nicht weiter.

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

/* Reihen Parallelwiderstand */
int Abfrage_Rechnung();
float Abfrage_Widerstaende();
float Rechnung_Reihe();
float Rechnung_Parallel();
float x;
int main(void) //wenn INT davor steht, muss am ende return X stehen, bei void erwartet er nichts am ende
{
float r[10]; //Array deklariert (FLießkommerzahlen)
int anz;
int wahl;
int i;
float rges;//wegen den Kommazahlen, welche als ergebnis erscheinen können
float leitwert;
float x[1];
x[1]=1;

printf ("Ich rufe Das Unterprogramm Auswahl_Rechnung auf\n");
Abfrage_Rechnung();

while(Abfrage_Rechnung!=0) {

if (Abfrage_Rechnung!=0)
{ //Zahlenabfrage
printf ("Ich rufe Das Unterprogramm Abfrage_Widerstaende auf\n");
Abfrage_Widerstaende();

if (Abfrage_Rechnung==01111111)
{//Reihenschaltung
printf ("Ich rufe Das Unterprogramm Rechnung_Reihe auf\n");
Rechnung_Reihe();
}
else
{//Parallelschaltung brerchnet mit Leitwert
printf ("Ich rufe Das Unterprogramm Rechnung_Parallel auf\n");
Rechnung_Parallel();
}

}
else //Sprung zum ende des Programmes
{
printf("Fertig\n");
}

}
return 0;
}
int Abfrage_Rechnung(void){ //Abfrage der Rechenart
int wahl;

printf("\nWahl der Widerstandsberechnung:\n");
printf("1 Reihenschaltung\n");
printf("2 Parallelschaltung\n");
printf("0 Programmende\n");
scanf("%d",&wahl);
return wahl;
}
float Abfrage_Widerstaende(void){
int anz;
int i;
float r[10];
printf("Geben Sie die Anzahl der Widerstaende ein:\n\n");
scanf("%d",&anz);

for (i=0;i<anz;i++)
{
printf("Geben Sie den %d. Widerstandswert in Ohm ein:\n",i+1);
scanf("%f",&r);

}

for (i=0;i<anz;i++)
printf("R[%d] = %5.2f Ohm\n",i+1,r);

return r[10];
}
float Rechnung_Reihe(){
float rges;
int i,anz;
float r[10];
rges=0;
for (i=0;i<anz;i++)
rges=rges+r;
printf("Der Gesamtwiderstand betraegt %5.2f Ohm",rges);

}
float Rechnung_Parallel(void){
int i,anz;
float rges, leitwert;
float r[10];


leitwert=0;
for (i=0;i<anz;i++)
leitwert=leitwert+1/r;
rges=1/leitwert;
printf("Der Gesamtwiderstand betraegt %5.2f Ohm",rges);
}
 
Moin,

zum einen: benutze bitte die Code-Tags! So bekommt man ja Augenkrebs!
Zum zweiten: bitte beschreibe Dein Problem so, dass es für andere auch verständlich ist!

Welches 'Unterprogramm' (der richtige begriff wäre hier "Methode" oder "Funktion") meinst Du denn?
Was erwartest Du? Was passiert stattdessen?

VG Klaus
 
Hallo mindtrip_1,

ist dein Thema noch relevant? Ansonsten bitte einmal entsprechend markieren.
Falls ja:

Zur besseren Lesbarkeit für alle anderen hier nochmal dein Code in Tags:
C:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

/* Reihen Parallelwiderstand */
int Abfrage_Rechnung();
float Abfrage_Widerstaende();
float Rechnung_Reihe();
float Rechnung_Parallel();
float x;

int main(void) //wenn INT davor steht, muss am ende return X stehen, bei void erwartet er nichts am ende
{
    float r[10]; //Array deklariert (FLießkommerzahlen)
    int anz;
    int wahl;
    int i;
    float rges;//wegen den Kommazahlen, welche als ergebnis erscheinen können
    float leitwert;
    float x[1];
    x[1] = 1;

    printf("Ich rufe Das Unterprogramm Auswahl_Rechnung auf\n");
    Abfrage_Rechnung();

    while (Abfrage_Rechnung != 0) {

        if (Abfrage_Rechnung != 0)
        { //Zahlenabfrage
            printf("Ich rufe Das Unterprogramm Abfrage_Widerstaende auf\n");
            Abfrage_Widerstaende();

            if (Abfrage_Rechnung == 01111111)
            {//Reihenschaltung
                printf("Ich rufe Das Unterprogramm Rechnung_Reihe auf\n");
                Rechnung_Reihe();
            }
            else
            {//Parallelschaltung brerchnet mit Leitwert
                printf("Ich rufe Das Unterprogramm Rechnung_Parallel auf\n");
                Rechnung_Parallel();
            }

        }
        else //Sprung zum ende des Programmes
        {
            printf("Fertig\n");
        }

    }
    return 0;
}

int Abfrage_Rechnung(void) { //Abfrage der Rechenart
    int wahl;

    printf("\nWahl der Widerstandsberechnung:\n");
    printf("1 Reihenschaltung\n");
    printf("2 Parallelschaltung\n");
    printf("0 Programmende\n");
    scanf("%d", &wahl);
    return wahl;
}

float Abfrage_Widerstaende(void) {
    int anz;
    int i;
    float r[10];
    printf("Geben Sie die Anzahl der Widerstaende ein:\n\n");
    scanf("%d", &anz);

    for (i = 0; i < anz; i++)
    {
        printf("Geben Sie den %d. Widerstandswert in Ohm ein:\n", i + 1);
        scanf("%f", &r);

    }

    for (i = 0; i < anz; i++)
        printf("R[%d] = %5.2f Ohm\n", i + 1, r);

    return r[10];
}

float Rechnung_Reihe() {
    float rges;
    int i, anz;
    float r[10];
    rges = 0;
    for (i = 0; i < anz; i++)
        rges = rges + r;
    printf("Der Gesamtwiderstand betraegt %5.2f Ohm", rges);
}

float Rechnung_Parallel(void) {
    int i, anz;
    float rges, leitwert;
    float r[10];


    leitwert = 0;
    for (i = 0; i < anz; i++)
        leitwert = leitwert + 1 / r;
    rges = 1 / leitwert;
    printf("Der Gesamtwiderstand betraegt %5.2f Ohm", rges);
}

Du kannst Code formatiert einfügen, indem du ihn (mit eckigen Klammern statt runden) zwischen die Tags schreibst:
(CODE=c)dein code(/CODE)
Er wird dadurch nicht nur sehr viel angenehmer für andere zu lesen, sondern du kannst auch von einer schnelleren Antwort ausgehen, da man sich natürlich am liebsten immer erst die Fragen vornimmt, die angenehm zu lösen sind.

Wie von vfl_freak bereits erwähnt, werden Unterprogramme in C Funktionen genannt. Faktisch hast du natürlich recht. Man kann Funktionen auch als Unterprogramme bezeichnen. Das ist jedoch nicht gängig und sorgt für Verwirrung. Die erwähnten Methoden wären Funktionen als Teil einer Klasse. Da C nicht objektorientiert ist, gibt es solche hier nicht. Bleiben wir also bei Funktionen.

Deine Verwendung der Funktionen ist etwas seltsam und zeigt, dass das Verständnis für die Sprache noch etwas fehlt. Wenn dir die Aufgabe ohne weitere Vorkenntnisse so hingeworfen wurde, ist das aber wohl auch kein Wunder.

Zuerstmal besteht der Kopf einer Funktion aus dessen Namen und den Typen der übergebenen Parameter bzw. deren lokale Bezeichnung. Dabei ist der Name der Funktion in Wirklichkeit ein Pointer auf den Speicher, an dem der auszuführende Code gespeichert ist. Ausgeführt wird dieser Code - also die Funktion - indem der Name (der für die Adresse steht) mit runden Klammern geschrieben wird und entsprechenden Argumenten falls benötigt. In deinem Code hast du ifs wie:

C:
if (Abfrage_Rechnung==01111111)
{//Reihenschaltung
printf ("Ich rufe Das Unterprogramm Rechnung_Reihe auf\n");
Rechnung_Reihe();
}

In diesem Fall vergleichst du den Pointer auf den Codeabschnitt mit der Dezimalzahl 1111111. Daher kommt deine Warning:
[Warning] comparison between pointer and integer [enabled by default]

In der Funktion gibst du das Ergebnis der Auswahl zurück und das willst du hier offensichtlich verwenden. Mit dem Namen der Funktion hast du einen Pointer und mit runden Klammern dahinter rufst du die Funktion erneut auf, was eine erneute Eingabe zur Folge hätte. Beides ist kaum das, was du willst. Du erreichst, was du vermutlich willst, wenn du die Funktion anfangs einmal aufrufst und die Rückgabe - also die Auswahl - speicherst, um sie wiederzuverwenden.

C:
wahl = Abfrage_Rechnung();

while (wahl != 0) {

    if (wahl != 0)
        ...

Das wäre die einfache Möglichkeit, das Ergebnis deiner Funktion weiterzuverwenden. So wie ich das sehe, hast du im folgenden Code aber versucht, ein switch nachzubilden. Sieh dir dazu einmal den Abschnitt zu Switch Case aus dem c-howto.de Tutorial an.

Du könntest deinen Code also so gestalten, dass du die Abfrage zwar schon direkt im Schleifenkopf machst, die Auswertung des Ergebnisses aber über case-Statements erfolgt. Da die Auswahl in der Schleife niemals 0 sein kann (denn dann hätte die Schleife abgebrochen und der Teil darin wäre nicht ausgeführt worden), ist das erste if redundant. Du kannst den darin enthaltenen Code herausnehmen und vor das switch schreiben.

Das Ergebnis einer Zuweisung ist immer das, was zugewiesen wurde. Somit kannst du den Code in folgender Weise umformulieren:
C:
    printf("Ich rufe Das Unterprogramm Auswahl_Rechnung auf\n");

    while (wahl = Abfrage_Rechnung()) {
        //Zahlenabfrage
        printf("Ich rufe Das Unterprogramm Abfrage_Widerstaende auf\n");
        Abfrage_Widerstaende();

        switch (wahl)
        {
        case 1://Reihenschaltung
            ...

Nun versuchst du in der Funktion Abfrage_Widerstaende() lokal in der Funktion ein Array zu deklarieren und dieses über return nach außen zu geben. Zuerst: Etwas lokal deklariertes verschwindet immer am Ende des Scopes, also des Gültigkeitsbereichs, in dem es deklariert wurde. In deiner Funktion ist das der Bereich zwischen den geschweiften Klammern, die den Funktionsblock darstellen. Was du außerdem versuchst zurückzugeben ist nicht das ganze Array, sondern das (nullbasiert) 10. Element von r. Da in der Deklaration für r angegeben wurde, dass es 10 Elemente hat, reichen die Indizes dieser 10 Elemente von 0 bis 9. Du versuchst also ein (1-basiert) 11. Element zurückzugeben, das nicht existiert und löst dabei noch einen Speicherzugriffsfehler aus. Für das, was du möchtest, gibt es zwei Möglichkeiten. Du kannst entweder den Speicher selber (dynamisch, also zur Laufzeit) reservieren, damit er nicht beim Verlassen der Funktion ungültig wird, oder du erstellst das Array gleich außerhalb der Funktion und gibst ihr lediglich eine Adresse mit, worauf sie zu schreiben hat. Hier gehe ich von letzterem aus, da das anfängerfreundlicher ist. Um deine Berechnung sinnvoll arbeiten zu lassen, brauchst du die Anzahl der tatsächlich beschriebenen Werte in dem Array, da es faktisch 10 Elemente hat und dein Programm später nicht mehr wissen kann, wie viele du davon nun beschrieben hast. Ein sinnvoller Rückgabewert wäre somit die Anzahl der eingetragenen Widerstände.

C:
scanf("%f", &r);

Beim Zugriff auf Elemente von r steht hier immer r statt
C:
r[0]

Die Forensoftware erkennt diesen Text als BB-Code und macht des Rest des Textes kursiv, statt den Indexzugriff zu schreiben. Deinen Code künftig in Code-Tags zu packen, wird das verhindern.

Da ich nicht erkennen kann, ob du hier nur r oder einen Indexzugriff geschrieben hast (mit dem der Code völlig korrekt wäre):

Der Name eines Arrays beinhaltet selber einen Pointer (also die Adresse) auf das erste Element des Arrays. scanf erwartet zwar einen Pointer, das ist richtig. Aber es erwartet wie im Formatstring angegeben einen Pointer auf einen float. Anders: Dein Argument soll vom Typ *float sein. Was du ihm mit dem & gegeben hast, ist ein Pointer auf den Pointer auf einen Float: **float. Du willst, dass er bei jeder Iteration auf das jeweils nächste Element schreibt. Da r selber auf das 1. Element zeigt, kannst du ihn diesen Pointer errechnen lassen, indem du das entsprechende i hinzuaddierst. Ein Pointer wird bei Addition mit einem Integer immer um die entsprechende Anzahl Elemente weitergeschaltet. Die ganze Funktion sieht damit so aus:
C:
int Abfrage_Widerstaende(float r[]) {
    int anz;
    int i;
    printf("Geben Sie die Anzahl der Widerstaende ein:\n\n");
    scanf("%d", &anz);

    for (i = 0; i < anz; i++)
    {
        printf("Geben Sie den %d. Widerstandswert in Ohm ein:\n", i + 1);
        scanf("%f", r+i);

    }

    for (i = 0; i < anz; i++)
        printf("R[%d] = %5.2f Ohm\n", i + 1, r[i]);

    return anz;
}

Die Berechnungen für die Reihenschaltung und die Parallelschaltung können die Werte, die lokal in der main deklariert wurden, nicht sehen. Um sie verwenden zu können, musst du sie übergeben.
Außerdem hast du angegeben, dass die Funktionen jeweils einen float zurückgeben, aber kein return dort stehen. In dem Fall wird automatisch 0 returnt. Das macht deinen Code nicht unkompilierbar, ist aber nicht unbedingt sinnvoll. Da du die Ausgabe über die Konsole machst und das Ergebnis nicht weiter verwendest, würde ich den Rückgabetypen hier einfach auf void setzen.

Auch hier hat der BB-Code deinen Indexzugriff verschwinden lassen.

Beide Funktionen zusammen sehen dann so aus:
C:
void Rechnung_Reihe(float r[], int anz) {
    float rges = 0;
    int i;

    for (i = 0; i < anz; i++)
        rges = rges + r[i];
    printf("Der Gesamtwiderstand betraegt %5.2f Ohm", rges);
}

void Rechnung_Parallel(float r[], int anz) {
    int i;
    float rges, leitwert;

    leitwert = 0;
    for (i = 0; i < anz; i++)
        leitwert = leitwert + 1 / r[i];
    rges = 1 / leitwert;
    printf("Der Gesamtwiderstand betraegt %5.2f Ohm", rges);
}

Abschließend bleibt dann nur noch die korrigierte Version der main. Das Einzige, was mir darin nicht so ganz klar ist, ist der Vergleich mit der Zahl 1111111. Zuerst mal wolltest du scheinbar eine Binärzahl schreiben. Das kannst du erreichen, indem du 0b1111111 schreibst. Die eingegebene Zahl wird dann als Binärzahl interpretiert. Äquivalent dazu steht 0xA7 für eine Hexadezimalzahl. Ich erkenne aber nicht den Sinn dieses Vergleichs. Mit den ifs hättest du mit 1 vergleichen müssen, da sie die Auswahl der Reihenschaltung darstellt. Übrigens brauchst du die Variablen, die in den Funktionen verwendet werden, nicht in der main zu deklarieren. Sie sind im Gültigkeitsbereich der Funktionen sowieso nicht sichtbar. Mit der switch-case-Struktur sieht die main so aus:

C:
int main(void) //wenn INT davor steht, muss am ende return X stehen, bei void erwartet er nichts am ende
{
    float r[10]; //Array deklariert (FLießkommerzahlen)
    int anz;
    int wahl;

    printf("Ich rufe Das Unterprogramm Auswahl_Rechnung auf\n");
    while (wahl = Abfrage_Rechnung()) {
        //Zahlenabfrage
        printf("Ich rufe Das Unterprogramm Abfrage_Widerstaende auf\n");
        anz = Abfrage_Widerstaende(r);

        switch (wahl)
        {
        case 1:
            //Reihenschaltung
            printf("Ich rufe Das Unterprogramm Rechnung_Reihe auf\n");
            Rechnung_Reihe(r, anz);
            break;
        case 2:
            //Parallelschaltung brerchnet mit Leitwert
            printf("Ich rufe Das Unterprogramm Rechnung_Parallel auf\n");
            Rechnung_Parallel(r, anz);
            break;
        }
    }

    printf("Fertig\n");
    return 0;
}

Ich kann dir das c-howto Tutorial sehr empfehlen. Für meine Anfänge hat das auch sehr geholfen. Ansonsten gibt es hier im Forum einige sehr anfängerfreundliche Tutorials.

Gruß,
Neonof
 
Zuletzt bearbeitet:
Zurück