Verständnisfrage zu Headerfiles
-
Für´s Studium soll ich folgenede Aufgabe bearbeiten:
Erstelle ein Programm euklid.c das aus zwei Zahlen den ggT und das kgV berechnet (hab ich, läuft)
2. Erstellen sie eine Header-Datei "euklid.h" mit den zugehörigen Prototypen/Deklarationen der Funktionen aus Schritt 1.
3. Erstellen sie nun ein C-Programm, das zwei Eingaben von der Konsole liest und dann ggT und kgV berechnet mittels der erstellten Funktionen.
Jetzt ist mir leider nicht ganz klar, wie ich das mit der Header-Datei genau machen muss, da dass was in unserem Skript steht, dafür anscheinend nicht funktioniert. Leider kann ich keine Teile des Skripts kopieren (Secured und Copyright).
Jetzt habe ich folgende Dateien:
euklid.c
/* *This Program calculate the gcD with euklid algorithm */ #include <stdio.h> #include "euklid.h" int a, b, startA, startB, c; void calc(int, int); void changeSign() { if(a < 0) a = a * (-1); if(b < 0) b = b * (-1); startA = a; startB = b; } void gcd() { while (a != b) if (a < b) b -= a; else a -= b; } void lcm() { c = (startA / a) * startB; } void calc(int A, int B) { a = A; b = B; changeSign(); gcd(); printf ("The GCD is: %u\n", a); lcm(); printf ("7The LCM is: %u\n", c); }
euklid.h (Hier weiß ich halt nicht richtig wie mans machen muss)
/*Prototyp*/ extern void calc(int A, int B); extern void changeSign(); extern void gcd(); extern void lcm();
inputeuklid.c
# include <stdio.h> # include "euklid.h" void main() { int A, B; printf("Please type first number: "); scanf("%u", A); printf("\nPlease type second number: "); scanf("%u", B); calc(A, B); }
Ich bin neu in C und es stellt sich mir vor allem die Frage ob sich die Variablen einfach so übergeben lassen.
Und wenn ich versuche inputeuklid.c zu compilieren, bekomme ich folgende Fehlermeldung:undefined reference to 'calc'.
Ich benutze CodeBlocks zum Programmieren mit GNU GCC Compiler (-std=c99) auf Windows 8.1 64bit.
Und kann mir jemand nen gutes Buch empfehlen?
-
Du musst in deinem Projekt noch
euklid.c
bekannt geben (Project -> Add Files)Es sind aber noch einige Fehler drin
Datei:Zeile
euklid.c:8 Globale Variablen sind Schrott und die Wurzel allen Übels.
euklid.c:9 Die Zeile kannst du weglassen. Die steht schon in euklid.h
euklid.c:11 Die Funktion macht nicht das, was der Name suggeriert: Besser absolute oder betrag. Und dann bitte als richtige Funktion mit Parametern und für eine Variableint betrag(int a);
euklid.c:21 Bitte als richtige Funktion mit Parametern und Rückgabewert
euklid.c:30 Bitte als richtige Funktion mit Parametern und Rückgabewerteuklid.h:alle das extern kannst du bei Funktionsdeklarationen weglassen
inputeuklid.c:8 %u ist für unsigned int. Der Adressoperator fehlt.
inputeuklid.c:10 %u ist für unsigned int. Der Adressoperator fehlt.
Der Formatspecifier (%u) muss zum Variablentyp (int) passen. Tut es hier nicht.
-
Also ich habe das ganze jetzt mal etwas angepasst, leider bekomme ich immernoch einen Fehler. Aber erstmal der Code:
euklid.c
#include <stdio.h> #include "euklid.h" int betrag(int x) { if(x < 0) x = x * (-1); return x; } int gcd(int a, int b) { while (a != b) if (a < b) b -= a; else a -= b; return a; } int lcm(int startA, int startB, int a) { int c = (startA / a) * startB; return c; } void calc(int x, int y) { int a, b, c, startA, startB; startA = x; startB = y; a = betrag(x); b = betrag(y); a = gcd(a, b); printf ("The GCD is: %i\n", a); c = lcm(startA, startB, a); printf ("7The LCM is: %i\n", c); }
euklid.h
extern void calc(int A, int B); extern int changeSign(); extern int gcd(); extern int lcm();
inputeuklid.c
# include <stdio.h> # include "euklid.h" void main() { int x, y; printf("Please type first number: "); scanf("%u", x); printf("\nPlease type second number: "); scanf("%u", y); calc(x, y); }
Beim Compilieren von euklid.c bekomme ich den Fehler:
undefined reference to 'WinMain@16'
und bei inputeuklid immernoch:
undefined reference to 'calc'
Dann hast du geschrieben:
Du musst in deinem Projekt noch euklid.c bekannt geben (Project -> Add Files)
Ich arbeite mit einzelnen Dateien, habe also kein Projekt in CodeBlocks offen. Wie muss man das bewerkstelligen?
inputeuklid.c:8 %u ist für unsigned int. Der Adressoperator fehlt.
inputeuklid.c:10 %u ist für unsigned int. Der Adressoperator fehlt.
Der Formatspecifier (%u) muss zum Variablentyp (int) passen. Tut es hier nicht.Man muss doch aber %u verwenden, da die Eingaben auch negativ sein können oder nicht? Was meinst du mit fehlendem Adressoperator? Wie müsste es denn aussehen?
Ich hoffe, das euklid.c jetzt soweit passt. Die Funktionen hab ich geändert mit Ein- und Rückgabewerten und habe die globalen Variablen entfernt. Das extern lasse ich aber für meine eigene bessere Übersicht stehen, tut ja niemandem weh. Muss ich dieses Speicherklassen-Spezifizierer auch in inputeuklid.c vor calc() setzen? Denn wenn bekomme ich andere Konflikte mit den Typen, warum auch immer.
G:\dev\c\uni\inputeuklid.c||In function 'main':|
G:\dev\c\uni\inputeuklid.c|11|warning: type defaults to 'int' in declaration of 'calc' [enabled by default]|
G:\dev\c\uni\inputeuklid.c|11|warning: parameter names (without types) in function declaration [enabled by default]|
G:\dev\c\uni\inputeuklid.c|11|error: conflicting types for 'calc'|
G:\dev\c\uni\euklid.h|2|note: previous declaration of 'calc' was here|
||=== Build finished: 1 errors, 2 warnings (0 minutes, 0 seconds) ===|EDIT:
Ich habe jetzt inputeuklid.c nochmal etwas geändert bei der Funktion calc() in:
extern void calc(int x, int y);
Jetzt bekomme ich keine Fehler mehr, das Programm startet, stirbt allerdings nach der Eingabe der ersten Zahl. Liegt das an den Adressoperatoren?
EDIT2:
OK, ja voll vercheckt mit dem Adressoperator
Leider wird aber calc() nicht ausgeführt wie es scheint. Nach der Eingabe zweier Zahlen, beendet das Programm einfach ohne Ausgabe.
-
Ace_KC schrieb:
Man muss doch aber %u verwenden, da die Eingaben auch negativ sein können oder nicht?
Das u steht für
unsigned
. Also vorzeichenlos (nur positiv).
Dann muss aber auch der Variablentyp dazu passen.
Da du als Variablentypint
hast, musst du %d oder %i nehmen.Ace_KC schrieb:
Leider wird aber calc() nicht ausgeführt wie es scheint. Nach der Eingabe zweier Zahlen, beendet das Programm einfach ohne Ausgabe.
Wie startest du denn das Programm?
Doppelclick mit der Maus? Dann schließt sich das Fenster schneller als du die Ausgabe sehen kannst.
Aus der Konsole heraus, wie man es bei einem Konsoleprogramm macht? Dann kannst du die Ausgabe sehen.
Mit Ctrl-F10 (oder über das Menü Build-Run)? Da lässt Code::Blocks das Fenster offen.
-
Ich starte das Program aus CodeBlocks raus, Konsole geht auf und nach Eingabe zweier Zahlen kommt das:
Process returned 1 (0x1) execution time : 5,274 s
Press any key to continue.Wenn ich "extern void calc()" benutze, scheint es als wäre es eine neue Deklaration ohne Funktion. Wenn ich nur "calc()" benutze, dann ist es wieder "undefined reference 'calc'".
Wenn es mit extern void natürlich ne neue Deklaration ist, ist klar das nichts weiter ausgeführt wird.
-
Bei mir läuft dein Programm.
Hast du jetzt ein Projekt (Console application) gemacht?
Welche Warnungen gibt der Compiler aus?
-
Habs jetzt in ein Projekt gepackt, dann funktioniert es auch. Aber es muss doch auch irgendwie ohne Projekt gehen oder nicht?
-
Ja.
Du kannst den gcc per Hand aufrufen. Dann musst du aber auch alle .c Dateien mit angeben.
Oder du machst dir ein
makefile
.Wie du das mit Code::Blocks nutzen kannst musst du suchen.
Es werden alle .c-Dateien einzeln zu Objectdateien (.o oder .obj) compiliert.
Alles was bei #include angegeben ist, wird dabei in der jeweiligen .c-Datei verarbeitet.Danach werden die Objectdateien mit den Bibliotheken zu einem ausführbaren Programm zusammengebunden. Dies macht der Linker.
Compiler und Linker suchen sich nicht die benötigten Dateien. Die musst du mit angeben.
Darum das Projekt bzw. makefile. Da kannst du Abhängigkeiten definieren, damit nur geänderte bzw. davon abhängige Dateien neu übersetzt werden.
-
Ah ok, danke.
-
Was noch nicht erwähnt wurde: die Prototypen in der Headerdatei sollten aber auch zu den Funktionen in der Source-Datai passen (inkl. Parameter).
Test: einfach die Funktion 'calc' an den Anfang innerhalb von "euklid.c" stellen...