C Laufvariable über mehrere Funktionen hinweg

fatSquirrel

Ensign
Registriert
Juni 2014
Beiträge
201
Hallo,
wir haben vor ein paar Wochen angefangen C zu programmieren und dabei bin ich auf folgendes Problem gestoßen.

Das Programm speichert über mehrere Funktionen Messwerte in einem Array. Dabei soll die Indexnummer über n deklariert sein. Ich habe also den Array messwerte[n] in meiner main Funktion angelegt. Nun soll die erste Funktion z.B. die ersten 5 Werte im Index 0-4 ablegen und die zweite Funktion im Index 5-8. Jetzt überschreibt meine zweite Funktion aber immer meine Messwerte der ersten...
Weiß jemand von euch, wie ich das Problem lösen kann?

//Funktion
int messungAgE(int array[], int anzahl, int speicherplatz){
for(...){
speicherplatz++;
}
return speicherplatz;
}

//Main
int n=0;
messungAgE(messwerte, ader, n);

Ich dachte eigentlich, dass dabei n in der Funktion größer wird und am Ende wieder zurückgegeben wird. Das scheint aber nicht der Fall zu sein.


lg fatSquirrel
 
Schreib:
n = messungAgE(messwerte, ader, n);
 
Danke für den Tipp. Das funktioniert soweit erstmal außer, dass das Programm jetzt Abstürzt, sobald das case beim break ankommt.
printf("%d", n);
break;
Der print-Befehl wird noch ausgegeben und danach kommt "Das Programm funktioniert nicht mehr".
 
Ich weiß nicht was dein Programm an der Stelle überhaupt macht davor/danach... poste den umliegenden Code.
Debugge dein Programm oder so.
Gibts keinen aussagekräftigeren Fehler(code) oder sonst was?
 
Das ist der komplette case:

case 49: printf("\n");

ader = eingabeAder();
laenge = eingabeLaenge();
size = arrayGroesse(ader);

//Array erstellen
messwerte = (int *)malloc(size);
if (messwerte != NULL){
printf("");
}
else{
printf("Der Speicher ist belegt!\n");
}

printf("\nAlle Messungen sind in Kiloohm einzutragen!\n\n");
n=messungAgE(messwerte, ader, n);
n=messungOhmKm(messwerte, ader, n, laenge);
n=messungAgA(messwerte, ader, n);

printf("%d", n);
break;


Nach dem case kommt nur noch return 0.
Einen Fehlercode bekomme ich nicht weiter.
 
Pack dein Code mal in Code klammern
HTML:
[CODE][/CODE]
dann kann man ihn besser lesen.
 
Zuletzt bearbeitet:
Ich pack euch einfach mal den ganzen Code hierein.

Code:
//Bibliotheken
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

//Menüauswahl
char menueAuswahl(){
	char a;

	fflush(stdin);
	printf("1. Testdurchlauf\n2. Simulierte Messwerte\n3. Exit\nWas wollen Sie tun? ");
	a = getchar();	
}

//Aderzahl eintragen mit Ü-Adern
int eingabeAder(){
	int aderZahl;
	char b;

	printf("Eingabe Aderzahl: ");
	scanf_s("%d", &aderZahl);
	
	fflush(stdin);
	printf("Sind Ue-Adern vorhanden (j/n)? ");
	b = getchar();

	if (b == 'j'){
		aderZahl += 2;
	}

	return aderZahl;
}

//Kabellänge eintragen
int eingabeLaenge(){
	int kabelLaenge;

	printf("Eingabe Kabellaenge (in km): ");
	scanf_s("%d", &kabelLaenge);

	return kabelLaenge;
}

//Größe des Arrays
int arrayGroesse(int anzahl){
	int i, size = 0;

	for (i = 1; i <= anzahl - 1; i++){
		size += anzahl - i;
	}
	size += 2 * anzahl;

	return size;
}

//Messung Ader gegen Erde
int messungAgE(int array[], int anzahl, int speicherplatz){
	int i;

	for (i = 0; i < anzahl; i++){
		printf("Messung Ader %d gegen Erde: ", i + 1);
		scanf_s("%d", &array[speicherplatz]);
		speicherplatz++;
		//printf("%d", speicherplatz);
	}

	return speicherplatz;
}

//Ohm/km berechnen
int messungOhmKm(int array[], int anzahl, int speicherplatz, int km){
	int i;
	for (i = 0; i < anzahl; i++){
		array[speicherplatz] = array[i] / km;
		speicherplatz++;
	}

	return speicherplatz;
}

//Messung Ader gegen Ader
int messungAgA(int array[], int anzahl, int speicherplatz){
	int i, j;
	
	for (i = 0; i < anzahl; i++){
		for (j = i + 1; j < anzahl; j++){
			printf("Messung Ader %d auf Ader %d: ", i + 1, j + 1);
			scanf_s("%d", &array[speicherplatz]);
			speicherplatz++;
		}
	}

	return speicherplatz;
}

//Ausgabe Ader gegen Erde
void ausgabeAgE(int array[], int anzahl, int dokument){
	int i;

	for (i = 0; i < anzahl; i++){
		printf("Ader %3d gegen Erde: %6d kOhm\n", i + 1, array[i]);
		fprintf(dokument, "Ader %3d gegen Erde: %6d kOhm\n", i + 1, array[i]);
	}
}

/*
//Ader gegen Erde ausgeben
for (i = 0; i < ader1; i++){
printf("Ader %3d gegen Erde: %6d kOhm\n", i + 1, messwerte[i]);
fprintf(fp, "Ader %3d gegen Erde: %6d kOhm\n", i + 1, messwerte[i]);
}
*/

//Main
int main(){

	int ader, laenge, size;
	int i;
	int n = 0;
	int *messwerte;
	FILE *fp;
	int a, b, c;

Beginn:

	switch (menueAuswahl()){


	case 49: printf("\n");
		
		ader = eingabeAder();
		laenge = eingabeLaenge();
		size = arrayGroesse(ader);

		//Array erstellen
		messwerte = (int *)malloc(size);
		if (messwerte != NULL){
			printf("");
		}
		else{
			printf("Der Speicher ist belegt!\n");
		}

		printf("\nAlle Messungen sind in Kiloohm einzutragen!\n\n");
		a=messungAgE(messwerte, ader, n);
		b=messungOhmKm(messwerte, ader, a, laenge);
		c=messungAgA(messwerte, ader, b);
		
		printf("\n\nAusgabe der Messwerte:\n\n");
		
		//Textdokument öffnen
		fp = fopen("Auswertung.txt", "w");

		//überprüfen, ob Dokument existiert
		if (fp == NULL){
			printf("Datei konnte nicht geoeffnet werden!\n");
		}

		//Ausgabe
		else{
			ausgabeAgE(messwerte, ader, fp);
		}
		//printf("%d", n);
		break;


	case 50: printf("\n");
		
		printf("case 2");

		break;


	case 51: printf("\n");
		
		printf("Das Programm wird beendet!\n");
		
		break;


	default: printf("\n");
		
		printf("Keine gueltige Eingabe!\n\n");

		goto Beginn;

		break;
	}

	return 0;
}
 
Sorry, war bis jetzt weg, Vatertagsverpflichtungen...
Ich muss erstmal sagen, C ist nicht mein Spezialgebiet.

Mir fällt auf:
char menueAuswahl(){
char a;

fflush(stdin);
printf("1. Testdurchlauf\n2. Simulierte Messwerte\n3. Exit\nWas wollen Sie tun? ");
a = getchar();
}
Du returnst hier a ja garnicht?
Das a in main() ist nicht das selbe wie das a in menueAuswahl().


Du willst ja "1" eingeben für das erste case, kannst du das sofort mit ASCII 49 vergleichen ohne konvertierung?


//Ohm/km berechnen
int messungOhmKm(int array[], int anzahl, int speicherplatz, int km){
int i;
for (i = 0; i < anzahl; i++){
array[speicherplatz] = array / km;
speicherplatz++;
}

return speicherplatz;
}

Wär runden nicht besser als Kommastellen abschneiden?
 
Zuletzt bearbeitet:
Du returnst hier a ja garnicht?
Das a in main() ist nicht das selbe wie das a in menueAuswahl()
Problem Nummer 1, eine nicht returnende Funktion kann durchaus zu einem Absturz führen. Nämlich wenn der Compiler auch wirklich keinen ret-Befehl in den compilierten Code schreibt. Passiert mir bei C++/clang++3.6 hin und wieder, wenn ich mal ein return vergesse.

Danke für den Tipp. Das funktioniert soweit erstmal außer, dass das Programm jetzt Abstürzt, sobald das case beim break ankommt.
Problem Nummer 2: Du musst wohl etwas ausgiebiger testen. Per Debugger, printf-Debugging oder sowas einfach mal gucken, ob das Array auch wirklich groß genug ist oder ob Funktionen auf Stellen im Array zugreifen, die gar nicht existieren.

Einen use-after-free-Bug kann man ausschließen, weil du dein Array ja praktischerweise gar nicht erst freigibst. :freak:
Anders gesagt: Wenn das ganze läuft, bau unbedingt noch ein free(messwerte) ein ;)

Du willst ja "1" eingeben für das erste case, kannst du das sofort mit ASCII 49 vergleichen ohne konvertierung?
Da menueAuswahl einen char returnt bzw. returnen sollte, ja - aber
Code:
switch (menueAuswahl()) {
  case '1':
    [...]
    break;
}
wäre natürlich noch um einiges lesbarer.

Code:
goto Beginn;

Tu dir selbst einen Gefallen und löse das hier mit einer Schleife. GoTo hat in C sicherlich seine Daseinsberechtigung, aber die würde ich eher in der Fehlerbehandlung sehen:

Code:
  void* bla = malloc(...);
  if (do_stuff(bla) == VERY_BAD_ERROR)
    goto fail;
  
  [...]
  return 0;

fail:
  free(bla);
  return -1;
 
Ich hab es jetzt hinbekommen. Ich weiß nur nicht, wo genau der Fehler lag...
Dazu hab ich noch ein anderes Problem gelöst und jetzt habe ich auch wieder case 1-3.

@VikingGE
Wieso würdest du lieber eine while Schleife und nicht goto verwenden? Würde sich natürlich noch recht schnell ändern lassen. Hatte ich für die Fehleingaben jetzt auch erstmal verwendet.

Den aktuellen Code habe ich nochmal in den Anhang gepackt.
 

Anhänge

GOTO sollte man einfach nicht in höheren Sprachen verwenden, v.a. wenn man es einfach durch Schleifen bzw anderen Kontrollflusskram ersetzen kann.
In einigen Sprachen wurde GOTO ganz "verboten", es gibt es einfach nicht.

GOTO schmeißt dich einfach von irgendwo, irgendwo anders hin. Kann lesbarkeit behindern und Wurschtlcode erzeugen. Einfach schlechter Programmierstil.

Bitte schon garnicht von menueAuswahl() mit GOTO nach main zurückspringen Oo
 
Alles klar. In menueAuswahl springt er nur wieder an den Anfang von menueAuswahl.
Gibt es eigentlich einen befehl, der das Programm von alleine beendet (ohne nochmal eine Taste zu drücken)?
 
return; in der main().
Tipp: In einer Funktion können auch mehrere return stehen.

Ist zwar auch nicht 100% super Programmierstil, aber 1000x besser als GOTO irgendwohin.
 
Zuletzt bearbeitet:
Theobald93 schrieb:
GOTO sollte man einfach nicht in höheren Sprachen verwenden
Kannst du das auch irgendwie schlüssig begründen, oder sagst du das nur, weil es ein Dogma deiner Religion ist?

GOTO schmeißt dich einfach von irgendwo, irgendwo anders hin.
Bitte was? Goto schickt dich von einer ausdrücklich ausgewiesenen Stelle an eine bestimmte, eindeutige andere Stelle innerhalb derselben Funktion. Wenn du hier so kategorisch schlechte Ratschläge gibst, hab wenigstens ein grobes Verständnis, wovon du überhaupt redest.

Bitte schon garnicht von menueAuswahl() mit GOTO nach main zurückspringen Oo
Macht er nicht und könnte er nichtmal, wenn er wollte.

Jede "Empfehlung" der Art "XYZ sollte man nie tun, weil das ist voll schlechter Stil" ist am Ende nur persönliche Meinung und/oder Religion und deshalb nicht hilfreich, sondern letztendlich schädlich.

Und im Übrigen bin ich der Meinung, dass man in jedem Fall, egal worum es geht immer First-Class Continuations benutzen sollte. Weil das ist eine voll knorke Sache.
 
Zuletzt bearbeitet:
Darauf zu antworten wäre wohl sinnlos.
Macht er nicht und könnte er nichtmal, wenn er wollte.
Da hast du Recht, ich hab das Start: im menueAuswahl() überlesen.

Wirklich sehr höfliche Art, die du an den Tag (oder eher Nacht) legst.
 
Zuletzt bearbeitet:
Zurück
Oben