PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Kompilier-Fehler mit Dev-C++



-=kama=-
12.07.2004, 17:06
Ich bin gerade dabei mich in C++ ein zu arbeiten (unter Zuhilfenahme eines Buches) und habe als Einstieg einfach mal ein kleines Additionsprogramm geschrieben (ich weiß, nix dolles, aber ich hab ja auch erst am Freitag mit C++ bzw. überhaupt dem Programmieren angefangen ^_^).

Bei dem Buch mitgeliefert war auch die Authorenversion von Visual C ++ 6 (den ich schon jetzt furchtbar finde), habe mir als Alternative auch das Dev-C++/Mingw Package von Bloodshed installiert (DJGPP habe ich trotz Angabe der Umgebungs-Variablen nicht zum laufen bekommen da angeblich eine bestimmte datei nicht gefunden werden kann...).

So, nun zum eigentlichen Problem: wenn ich mein Rechner-Proggi mit VC++6 kompilieren lasse klappts ausgezeichnet, bei Dev-C++ bekomme ich eine Fehlermeldung....


#include <iostream>
using namespace std;

void main(void)
{
int zahl1, zahl2, ergebnis;
cout << "Bitte geben Sie eine Zahl ein:" << endl;
cin >> zahl1;
cout << endl;
cout << "Bitte geben Sie eine weitere Zahl ein:" << endl;
cin >> zahl2;

ergebnis = zahl1 + zahl2;

cout << endl;
cout << zahl1 " + " zahl2 " = " ergebnis;
}

...und zwar in Zeile 5, also der ersten geschweiften Klammer nach:


void main(void)

die Fehlermeldung lautet in etwa so:


'main' must int

Nun habe ich in einigen anderen Quelcodes gesehen dass dort die Mainfunction mit...


int main()

...deklariert wurde. In diesen Quellcodes wurden die Präprozessor-Amnweisungen übrigens auch mit...


include <iostream.h>

anstatt


include <iostream>
using namespace std;

...eingebunden. Mein Buch (nach welchem ich auch hauptsächlich arbeite) benutzt bei allen Übungen die letztere Variante, der Autor gibt allerdings an dass man


include <iostream.h>

benutzen soll wenn man einen älteren Compiler hat.

Unter VC++6 funktioniert es wie gesagt einwandfrei, aber ich will das Schrottding ehrlich gesagt nicht länger benutzen.

Um's kurz zu machen:


cout << "SOMEBODY HELP ME PLEASE!"

Ps.: Ich habe den Quellcode den ich oben angegeben habe nochmal aus dem Kopf geschrieben, da ich gerade nicht an meinem eigenen Rechner sitze. Deshalb kann es sein dasss nun ein paar Syntax-Error drin sind die im Original nicht waren. An denen liegt's also nicht... ;)

Jesus_666
12.07.2004, 18:12
1.) Microsofts obskures pseudo-C++, das ich nicht als echtes C++ ansehe, weil es sich nicht an den ANSI-Standard für C++ hält, hat main als void. Korrektes, standardkonformes C++ hat main als int. Benutze int main() (oder meinetwegen int main(void), was das gleiche ist).

2.) <*.h> hießen die STL-Header früher. Irgendwann wurde dann festgelegt, daß das .h überflüssig ist, seitdem heißen sie <*>. Laß' das .h weg, es sei denn der Compiler kann die includete Datei ohne .h nicht finden.
Mir ist keine Version von gcc/g++* bekannt, die noch das .h erwarten würde; wenn du mit .h includest bekommst du zur Kompilierzeit eine Warnung.

-=kama=-
12.07.2004, 18:27
Ja, danke für die schnelle Antwort.
Wundert mich allerdings trotzdem das in dem Buch überhaupt void main(void) benutzt wird, wenn es nur mit VC++ zu kompilieren ist. Der Autor hat nämlich geschrieben das die Code-Beispiele nicht explizit für VC++ geschrieben wurden sondern allesamt ebenfalls mit dem Borland Compiler getestet wurden. Ausserdem wird da behauptet der VC++6 sei ANSI/ISO-Konform...Naja, ich mag das Teil sowieso nicht, alleine die unglaublich nervige Projektverwaltung und die Tatsache dass dein simpler Tippfehler wie "ednl;" statt "endl;" das Programm zum Komplettabsturz bringt sind mir gehörig auf den Wecker gegangen.

Also, nochmal danke, ich werde das heute abend gleich mal ausprobieren. ^_^

Ineluki
12.07.2004, 19:24
wenn du dan dein Programm auf

int main(void)
umgeschrieben hast, darfst du natuerlich nicht vergessen, dass du dann auch einen return code zurueckgeben musst.

ein einfaches

return 0;
vor der letzten geschweiften Klammer sollte ein etwaiges Problem beheben.

BTW.. ich schiebs zwar mal auf die von dir beschriebenen Tippfehler, aber bei deiner letzten cout-zeile hast du ein beginnendes " vergessen ^^

Gruss Ineluki

-=kama=-
12.07.2004, 19:52
wenn du dan dein Programm auf


int main(void)
umgeschrieben hast, darfst du natuerlich nicht vergessen, dass du dann auch einen return code zurueckgeben musst.

ein einfaches


return 0;

vor der letzten geschweiften Klammer sollte ein etwaiges Problem beheben.


Öhm ja, wieder so eine Sache die in meinem Buch (zumindest in den bisherigen Programmbeispielen) überhaupt keine Verwendung gefunden hat, die mir aber in diversen Online Tutorials aufgefallen ist. Hat das auch etwas mit VC++ zu tun (Die Tatsache dass es im Buch nicht gemacht wurde)? So langsam fang ich an die Sinnhaftigkeit meiner Lernlektüre in Frage zu stellen...


BTW.. ich schiebs zwar mal auf die von dir beschriebenen Tippfehler, aber bei deiner letzten cout-zeile hast du ein beginnendes " vergessen ^^

Meinst du:


cout << zahl1 " + " zahl2 " = " ergebnis;

oder:


cout << "SOMEBODY HELP ME PLEASE!"

?

In beiden Fällen verstehe ich nicht ganz wo da ein " fehlt. zahl1, zahl2 und ergebnis sind ja Variablen, brauchen also afaik keine Anführungszeichen, und " + " und " = " haben beide je ein einleitendes " da sie ja hier als Konstante und nicht als Operatoren verwendet werden (hab ich doch richtig verstanden, oder? wenn nicht: klärt micht auf :) )

und bei "SOMEBODY HELP ME PLEASE!" sind doch auch beide Anführungszeichen vorhanden (allerdings hab ich das abschliesende semikolon vergessen ^_^)

Wie gesagt, ich hab dieses Wochenende erst mit dem ganzen Krempel angefangen, vorm Programmieren hab ich bisher immer zu viel Respekt gehabt. Daher bin ich über jedwede Richtigstellung eventueller Misskonzeptionen meinerseits mehr als dankbar.

Jesus_666
12.07.2004, 21:23
Original geschrieben von -=kama=-
Öhm ja, wieder so eine Sache die in meinem Buch (zumindest in den bisherigen Programmbeispielen) überhaupt keine Verwendung gefunden hat, die mir aber in diversen Online Tutorials aufgefallen ist. Hat das auch etwas mit VC++ zu tun (Die Tatsache dass es im Buch nicht gemacht wurde)? So langsam fang ich an die Sinnhaftigkeit meiner Lernlektüre in Frage zu stellen...
Also... Microsoft will, daß main() vom Typ void ist. Das heißt, es hat keinen Rückgabewert. ANSI will, daß main() vom Type int ist, also als Rückgabewert eine Ganzzahl hat. Mit einem main() als int mußt du natürlich auch eine Zahl zurückgeben; im Normalfall ist das 0.

BTW, folgende Zeile ist zwar anführungszeichentechnisch okay, aber aus einem anderen Grund nicht gut:

cout << zahl1 " + " zahl2 " = " ergebnis; // Bei cout müssen die einzelnen Teile mit << verbunden werden
cout << zahl1 << " + " << zahl2 << " = " << ergebnis; // besser

-=kama=-
12.07.2004, 21:48
Also... Microsoft will, daß main() vom Typ void ist. Das heißt, es hat keinen Rückgabewert. ANSI will, daß main() vom Type int ist, also als Rückgabewert eine Ganzzahl hat. Mit einem main() als int mußt du natürlich auch eine Zahl zurückgeben; im Normalfall ist das 0.

Hm..ja, macht Sinn. Werde ich in Zukunft also nicht mehr machen. :)


cout << zahl1 " + " zahl2 " = " ergebnis; // Bei cout müssen die einzelnen Teile mit << verbunden werden
cout << zahl1 << " + " << zahl2 << " = " << ergebnis; // besser

Hab ich gar nicht dran gedacht, ist aber irgendwie logisch jetzt wo ich's sehe. ^_^
Danke.

Ineluki
13.07.2004, 05:33
Das mit dem Anfuehrungszeichen hab ich verbrochen ... ich hatte mich einfach verlesen ^^

kann ja mal vorkommen ;)

-=kama=-
13.07.2004, 16:48
Das mit dem Anfuehrungszeichen hab ich verbrochen ... ich hatte mich einfach verlesen ^^

kann ja mal vorkommen ;)

Köpft ihn! :D

Naja, jedenfalls habe ich eure Ratschläge beherzigt und siehe da, es funzt!

Allerdings habe ich inzwischen ein anderes Problem:


#include <conio.h>
...
getch();

funktioniert einwandfrei, aber


#include <stdio.h>
...
getchar();

wird einfach ignoriert, sprich: das Programm wird nach einmaligem Durchlauf geschlossen. How comes?

Und wo ich grad schon mal dabei bin: ich habe mir mal dieses Rechenprogramm (http://forum.rpg-ring.com/forum/showthread.php?s=&threadid=29868) von Balbero angeschaut und - nachdem ich verstanden hab wie es funktioniert - in leicht modfizierter Form nachgebaut. Was mich daran aber stört ist dass das Programm nach Ausführung einfach zu Ende ist. Gibt es da nicht eine möglichkeit nach Ausführung der Funktion multiplikation(); wieder zu main(); zu "springen"? Ich hab einfach mal versucht die Rechenfunktionen (addition(); , multiplikation(); etc.) innerhalb von main zu deklarieren, aber das hat nicht _SO_GANZ_ (^_^) funktioniert. Irgendwelche Ideen wie man sowas am besten macht?

Jesus_666
13.07.2004, 17:26
Du kanst getchar() einfach in eine Schleife setzen:


int c = 0;
while (c != '.')
{
c=getchar();
putchar (c);
}
Dieses Beispiel gibt jedes eingegebene Zeichen aus, bis ein Punkt eingegeben wird.

die gleiche Lösung gilt für das Rechenprogramm: Mach' einfach in main() eine Schleife.


int main()
{
int befehl;

for (;;) // Main loop
{
// Haufen Code weggelassen

switch(befehl)

case 7: // Programm beenden
cout << endl << "Programm beenden" << endl;
return 0;
break;

case 1:
cout << endl;
Multiplizieren;

} // Main loop

return 255; // Diese Zeile sollte nie erreicht werden
}

-=kama=-
13.07.2004, 17:54
Das verstehe ich allerdings nicht:

case 1:
cout << endl;
Multiplizieren;

} // Main loop

Ich dachte man muss funktionen immer mit (); ansprechen, also


case 1:
cout << endl;
Multiplizieren(); // <---

} // Main loop

Warum nicht auch in diesem fall?

Und das hier ist mir auch nicht ganz klar:

for (;;) // Main loop

Damit lege ich doch die Bedingung für die Wiederholung der Schleife fest, oder? Was bedeuten dann die beiden semikolons? Ich kenne das nur so:


int i;
for (i = 1; i < 4; i++){
cout << "REPEAT";
}

Jesus_666
13.07.2004, 20:54
Beim Funktionsaufruf fehlen tatsächlich die Klammern.

Das for(;;) ist eine Schleife ohne Bedingungen. Sprich: Sie wird ewig wiederholt, solange man sie nicht irgendwie verläßt (entweder durch ein break oder durch return, bzw. exit()). Man kann genausogut auch while (true) hinschreiben, das hat den selben Effekt.
Man kann nicht einfach for() schreiben, weil für for die Schrebweise mit den Semikolon-getrennten Befehlen vorgeschrieben ist.
for(;;) läßt sich übersetzen zu: Mache zuerst nichts. Durchlaufe eine Schleife; bei jedem Durchlauf überprüfst du nicht, ob du sie beenden sollst und du tust auch nichts besonderes.

.drifting
13.07.2004, 20:57
Ist "for (;;)" nicht schlechter Stil? "while (true)" kapiert man doch eher... XD

-=kama=-
13.07.2004, 21:31
Das for(;;) ist eine Schleife ohne Bedingungen. Sprich: Sie wird ewig wiederholt, solange man sie nicht irgendwie verläßt (entweder durch ein break oder durch return, bzw. exit()). Man kann genausogut auch while (true) hinschreiben, das hat den selben Effekt.

Ok, ich glaube ich hab's verstanden. Nur noch eine letzte Sache (um auf Nummer sicher zu gehen):


case 7: // Programm beenden
cout << endl << "Programm beenden" << endl;
return 0;
break;


ist es das "return(0);" oder das "break;" welches die for-Schleife beendet? Denn breaks habe ich in einem switch ja mehrere (in meinem fall sinds fünf). Und z.B. nach...


case 3: //
cout << endl;
Division();
break;


...soll die Schleife ja von vorne beim "Auswahlmenü" beginnen. Falls das break; dort aber Schleife beendet, dann würde das ja nicht funzen.

Ich hoffe ich geh dir nicht auf den Keks mit der ganzen Fragerei... ^_^

.drifting
13.07.2004, 21:47
"break" beendet in diesem Fall den "switch"-Teil. Das "return" beendet die aktuelle Funktion (in diesem Fall das Programm).

-=kama=-
13.07.2004, 21:53
Okay, verstanden. Danke :)

Jesus_666
13.07.2004, 22:39
Original geschrieben von .drifting
"break" beendet in diesem Fall den "switch"-Teil. Das "return" beendet die aktuelle Funktion (in diesem Fall das Programm).
An sich wäre das break überflüssig, da es keinen Sinn macht, einen switch zu verlassen, nachdem man das Programm beendet hat. Allerdings würde sich der Compiler dann beschweren.

.drifting
13.07.2004, 23:29
Original geschrieben von Jesus_666
An sich wäre das break überflüssig, da es keinen Sinn macht, einen switch zu verlassen, nachdem man das Programm beendet hat. Allerdings würde sich der Compiler dann beschweren.

Hmm... eigentlich sollte das Programm dann in den nächsten "case"-Teil fallen, der unter dem aktuellen steht.

Jesus_666
14.07.2004, 00:06
Yup. Ich kann mich aber daran erinnern, daß g++ sich darüber mal beschwert hat... Warning, nicht Error. Interessanterweise kann ich das nicht replizieren. Könnte vielleicht daran liegen, daß ich inzwischen eine andere Version von g++ benutze. Vielleicht war's auch gcc, der laut geworden ist.

-=kama=-
14.07.2004, 23:25
Sodale, hier ist das Ergebnis:


#include <iostream>
#include <conio.h>
using namespace std;

int zahl1, zahl2, ergebnis, auswahl;

void ausrechnen(void){
cout << "\nBitte geben Sie eine Zahl ein:\n\n";
cin >> zahl1;
cout << "\nBitte geben Sie eine weitere Zahl ein:\n\n";
cin >> zahl2;

switch (auswahl){
case 1: ergebnis = zahl1 + zahl2;
break;
case 2: ergebnis = zahl1 - zahl2;
break;
case 3: ergebnis = zahl1 * zahl2;
break;
case 4: ergebnis = zahl1 / zahl2;
break;
}
cout << "\nErgebnis: " << ergebnis << endl
<< "\nDr" "\x81" "cken Sie eine beliebige Taste...";
getch();

}

int main(){
while (true){
cout << endl << endl
<< "W" "\x84" "hlen Sie eine Rechenart:\n" << endl
<< "Addieren <1>" << endl
<< "Subtrahieren <2>" << endl
<< "Multiplizieren <3>" << endl
<< "Dividieren <4>" << endl
<< "Programm Beenden <5>\n" << endl;
cin >> auswahl;

switch (auswahl){
case 1:
case 2:
case 3:
case 4: ausrechnen();
break;
case 5: return(0);
break;
}
}
}

Funzt dank euerer eurer Hilfe prächtig. Zwei kleine Problemchen gibt aber auch diesmal wieder:

- clrscr(); zum löschen des Fensters funktioniert nicht (ERROR: undefined function 'clrscr()'!!)


- ich hab versucht bei "case 4: ergebnis = zahl1 / zahl2" per Cast aus den Integern ein Double zu machen, hat aber nicht wirklich geklappt, weder mit "static_cast<double> (...)" noch mit "(double) (...)". Kann man Variablen überhaupt casten?

MuadDib
15.07.2004, 00:27
Original geschrieben von -=kama=-
- clrscr(); zum löschen des Fensters funktioniert nicht (ERROR: undefined function 'clrscr()'!!)

clrscr aus C++ kenn ich nicht, in Pascal hab ich davon gehört... versuch einfach folgendes:



printf("\033[2J"); printf("\033[0;0H");
\033 ist das Escape zeichen, [2J löscht den Bildschirm, und [0;0H setzt den Cursor zurück... alte C-Hacker-Kunst :D


- ich hab versucht bei "case 4: ergebnis = zahl1 / zahl2" per Cast aus den Integern ein Double zu machen, hat aber nicht wirklich geklappt, weder mit "static_cast<double> (...)" noch mit "(double) (...)". Kann man Variablen überhaupt casten?
probiers so:


ergebnis = (int) (((double) zahl1)/((double) zahl2));

Damit sollte es eigentlich laufen!

.drifting
15.07.2004, 02:45
Original geschrieben von MuadDib
clrscr aus C++ kenn ich nicht, in Pascal hab ich davon gehört... versuch einfach folgendes:



printf("\033[2J"); printf("\033[0;0H");
\033 ist das Escape zeichen, [2J löscht den Bildschirm, und [0;0H setzt den Cursor zurück... alte C-Hacker-Kunst :D

Also in Dev-C++ gehts schonmal nicht...

MuadDib
15.07.2004, 02:56
Original geschrieben von .drifting
Also in Dev-C++ gehts schonmal nicht...
Sorry... dürfte anscheinend nur unter Unix-Systemen laufen, wusste nicht, dass Windows damit nicht klarkommt (es liegt sicher nicht an Dev-C++, auch nicht am MinGW, sondern an der Windows-Kommandozeile, die anscheinend keine ANSI-Escape-Sequenzen unterstütz)

Als Windows-Variante eignet sich z.B. das:



#include <stdlib.h>
...
system("cls"); // externer System-Call

system("clear"); unter *nix...

Sauberer Programmierer sorgen natürlich für beide Varianten:



#ifdef WIN32
system("cls");
#else
printf("\033[2J"); printf("\033[0;0H");
#endif

-=kama=-
16.07.2004, 19:31
Zitat von Muad
clrscr aus C++ kenn ich nicht, in Pascal hab ich davon gehört...

Najo, das hab ich aus "C/C++ in 16 Teilen" (http://www.games-net.de/resource.php?action=download&id=24) von Sebastian Dietz. Er schreibt dazu folgendes:


clrscr()

Der Befehl clrscr() löscht einfach den Bildschirm. Dies sollte man auf alle Fälle machen, bevor das Programm startet. Und bei den Beispielprogrammen kann man ein clrscr() vor dem Anzeigen des Menüs einfügen, damit das Programm nicht den Bildschirm vollschreibt, sondern immer nur die aktuell wichtigen Informationen eingeblendet werden. Um clrscr() zu benutzen, muß man die Datei <conio.h> einbinden (durch eine weitere include-Anweisung). Probiere einfach mal einige Sachen damit aus.

Hier ein kleines Beispiel:


1 #include <iostream.h>
2 #include <stdio.h>
3 #include <conio.h>

4 int MeinX, MeinY;

5 void main(void)
6 {
7 clrscr();
8 gotoxy(1, 12);
9 cout << "Hier beginnt der Text bei (1, 12)";
10 getchar();
11 MeinX = 10;
12 MeinY = 3;
13 gotoxy(MeinX, MeinY);
14 cout << "Und hier bei (10, 3)";
15 getchar();
16 }



Aber vielleicht ist das auch nur wieder so 'ne VC++ -spezifische Sache die mit anderen Compilern nicht funzt. Ich werd's jetzt einfach mal mit deiner Variante Testen.


probier's so:
ergebnis = (int) (((double) zahl1)/((double) zahl2));

Da war ich ja schon nahe dran....hab aber die äußere Klammer um...

(double) zahl2 /(double) zahl2
...vergessen >_<

Jedenfalls danke für die Hilfe.

Jesus_666
16.07.2004, 22:07
conio.h ist eine Microsoft-spezifische Includedatei, die es erlaubt, die Windows-Kommandozeile zu interfacen. Sollte eigentlich mit Standard-C++ funktionieren; ich halte es trotzdem für schlechten Stil (was auf sämtliche Techniken zutrifft, die das Programm plattformspezifisch machen).

MuadDib
16.07.2004, 22:30
Original geschrieben von Jesus_666
conio.h ist eine Microsoft-spezifische Includedatei, die es erlaubt, die Windows-Kommandozeile zu interfacen. Sollte eigentlich mit Standard-C++ funktionieren; ich halte es trotzdem für schlechten Stil (was auf sämtliche Techniken zutrifft, die das Programm plattformspezifisch machen).
conio.h stammt eigentlich von Borland, und wurde später von MS übernommen, da es einfach zuviele verwendet hatten :) - komischerweise gibts die conio.h auch in MinGW, laufen tuts trotzdem nicht, wohl falsch implementiert...

EDIT: darn, nicht falsch implementiert, sondern gar nicht kompiliert... die Source-Files befinden sich im minGW-include-Verzeichnis...

Jesus_666
16.07.2004, 23:14
Original geschrieben von MuadDib
conio.h stammt eigentlich von Borland, und wurde später von MS übernommen, da es einfach zuviele verwendet hatten :)
Ich korrigiere mich: Windows-spezifisch. *schauder*