App installieren
How to install the app on iOS
Follow along with the video below to see how to install our site as a web app on your home screen.
Anmerkung: This feature may not be available in some browsers.
Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden.
Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
[C++] Simples aber merkwürdiges Problem
- Ersteller p4z1f1st
- Erstellt am
p4z1f1st
Grand Admiral Special
- Mitglied seit
- 28.04.2003
- Beiträge
- 9.722
- Renomée
- 81
- Prozessor
- AMD FX-6300
- Mainboard
- Gigabyte GA-970A-UD3
- Kühlung
- HEATKILLER® CPU Rev3.0 LC + HEATKILLER® GPU-X² 69x0 LT
- Speicher
- 2x 4096 MB G.Skill RipJawsX DDR3-1600 CL7
- Grafikprozessor
- AMD Radeon RX 480 8GB
- Display
- Dell U2312HM
- HDD
- Crucial m4 SSD 256GB
- Optisches Laufwerk
- Sony Optiarc AD-7260S
- Soundkarte
- Creative Labs SB Audigy 2 ZS
- Gehäuse
- Chieftec Scorpio TA-10B-D (BxHxT: 205x660x470mm)
- Netzteil
- Seasonic X-Series X-660
- Betriebssystem
- Microsoft Windows 10 Professional 64bit
- Webbrowser
- Mozilla Firefox
- Verschiedenes
- Watercool HTF2 Dual + 2x Papst 4412 F/2GL
Hi!
Ich darf nun in meinem Studium in den Genuß einer C++Vorlesung kommen und muss mich daher mit dem Blödsinn rumschlagen ^^
Jetzt sollen wir ne ganz einfache Aufgabe bewerkstelligen, die an sich net wirklich schwer ist:
Es soll einfach die Funktion cos(x) einmal in Bogenmaß und einmal in Grad angegeben werden (in 30° bzw. 1/6-pi Schritten), wobei man vorher wählen sollen kann, welches man ausgegeben haben will.
Gesagt getan, einfach ne For-schleife für die Abzählung der einzelnen 30er-Schritte (bzw. 1/6-pi Schritte) gebaut und davor dann eine noch einfacherere if-Schleife reingeschustert.
Jetzt ist mein Problem, dass er meine if-schleife nicht will, obwohl jene aus einer Variablen und insgesamt genau 2 Zeilen besteht:
(if (ausdruck1)
anweisung1
else
answeisung2
mein Visual C++ sagt mir im genauen Wortlaut "error C2181: Ungültiges 'else' ohne zugehöriges 'if'"
Hier mal mein Code:
Erstmal das und dann noch eine "Schönheitskorrekturfrage". Und zwar arbeiten wir z.Zt. ausschließlich mit <stdio.h>, statt mit dem mir von der Oberstufe bekannten <iostream> samt "using namespace std;" - Aber ich komme mit dem Befehl "scanf" nicht ganz klar und hab daher aufs altbewerte "cin >>" gegriffen.
Könnt mir einer das mal bissl anschaulich für mein Beispiel erklären? (Dann müsste ich auch net die iostream-bibliothek einfügen und es wäre einheitlicher, was mein Prof vermutlich haben will)
MfG p4z1
Ich darf nun in meinem Studium in den Genuß einer C++Vorlesung kommen und muss mich daher mit dem Blödsinn rumschlagen ^^
Jetzt sollen wir ne ganz einfache Aufgabe bewerkstelligen, die an sich net wirklich schwer ist:
Es soll einfach die Funktion cos(x) einmal in Bogenmaß und einmal in Grad angegeben werden (in 30° bzw. 1/6-pi Schritten), wobei man vorher wählen sollen kann, welches man ausgegeben haben will.
Gesagt getan, einfach ne For-schleife für die Abzählung der einzelnen 30er-Schritte (bzw. 1/6-pi Schritte) gebaut und davor dann eine noch einfacherere if-Schleife reingeschustert.
Jetzt ist mein Problem, dass er meine if-schleife nicht will, obwohl jene aus einer Variablen und insgesamt genau 2 Zeilen besteht:
(if (ausdruck1)
anweisung1
else
answeisung2
mein Visual C++ sagt mir im genauen Wortlaut "error C2181: Ungültiges 'else' ohne zugehöriges 'if'"
Hier mal mein Code:
Code:
#include <stdafx.h>
#include <stdio.h>
#include <math.h>
#define _USE_MATH_DEFINES
#define M_PI 3.141592654
#include <iostream>
using namespace std;
int main (void)
{
float d=0;
float e=M_PI/6;
int x;
int y=0;
int z=0;
printf("Fuer Bogenmass bitte '0' eingeben. Sonst Ausgabe in Grad.\n");
cin >> y;
if (y > 0)
printf("Ausgabe von Cos(x) in Grad\n");
for (x=0 ; x<=12 ; x++) // For-Schleife (solange x <= 12, Schleife ausführen)
{
printf("%d\n",z);
z=z+30; // z um 30° erhöhen
}
else
printf("Ausgabe von Cos(x) im Bogenmass\n");
for (x=0 ; x<=12 ; x++)
{
printf("%f\n",d);
d=d+e;
}
return 0;
}
Erstmal das und dann noch eine "Schönheitskorrekturfrage". Und zwar arbeiten wir z.Zt. ausschließlich mit <stdio.h>, statt mit dem mir von der Oberstufe bekannten <iostream> samt "using namespace std;" - Aber ich komme mit dem Befehl "scanf" nicht ganz klar und hab daher aufs altbewerte "cin >>" gegriffen.
Könnt mir einer das mal bissl anschaulich für mein Beispiel erklären? (Dann müsste ich auch net die iostream-bibliothek einfügen und es wäre einheitlicher, was mein Prof vermutlich haben will)
MfG p4z1
JKuehl
Grand Admiral Special
- Mitglied seit
- 22.06.2003
- Beiträge
- 7.903
- Renomée
- 145
- Standort
- Stockholm, Schweden
- Mitglied der Planet 3DNow! Kavallerie!
- Aktuelle Projekte
- POEM, SIMAP
- Lieblingsprojekt
- SIMAP, POEM
- Meine Systeme
- Q6600
- BOINC-Statistiken
- Folding@Home-Statistiken
- Prozessor
- Ryzen-3700x
- Mainboard
- Asus B350 Prime Plus
- Kühlung
- Fractal Design Celsius 240
- Speicher
- 48 GB Corsair LPX 3000
- Grafikprozessor
- 1080ti
- Display
- 28" Samsung 3840x2160
- SSD
- Samsung Evo 960 500Gb
- Soundkarte
- Creative X-Fi Titanium PCIe
- Netzteil
- Be Quiet Dark Power 650
- Betriebssystem
- Windows 10 64 Bit
du hast die { } vergessen bei IF und ELSE
Korrekte Syntax:
IF (...)
{
...
}
ELSE
{
}
Weglassen darfst du diese nur, wenn die Anweisung aus maximal einer Zeile besteht
.
EDIT :
.
scanf:
http://www.cplusplus.com/reference/clibrary/cstdio/scanf.html
Somit solltest du folgendes verwenden:
scanf ("%d",&i);
und natürlich noch bei sämtlichen Funktionsaufrufen darauf achten, Fehler abzufangen ( wollten zumindest meine Profs immer sehen.. ).
Korrekte Syntax:
IF (...)
{
...
}
ELSE
{
}
Weglassen darfst du diese nur, wenn die Anweisung aus maximal einer Zeile besteht
.
EDIT :
.
scanf:
http://www.cplusplus.com/reference/clibrary/cstdio/scanf.html
Somit solltest du folgendes verwenden:
scanf ("%d",&i);
und natürlich noch bei sämtlichen Funktionsaufrufen darauf achten, Fehler abzufangen ( wollten zumindest meine Profs immer sehen.. ).
p4z1f1st
Grand Admiral Special
- Mitglied seit
- 28.04.2003
- Beiträge
- 9.722
- Renomée
- 81
- Prozessor
- AMD FX-6300
- Mainboard
- Gigabyte GA-970A-UD3
- Kühlung
- HEATKILLER® CPU Rev3.0 LC + HEATKILLER® GPU-X² 69x0 LT
- Speicher
- 2x 4096 MB G.Skill RipJawsX DDR3-1600 CL7
- Grafikprozessor
- AMD Radeon RX 480 8GB
- Display
- Dell U2312HM
- HDD
- Crucial m4 SSD 256GB
- Optisches Laufwerk
- Sony Optiarc AD-7260S
- Soundkarte
- Creative Labs SB Audigy 2 ZS
- Gehäuse
- Chieftec Scorpio TA-10B-D (BxHxT: 205x660x470mm)
- Netzteil
- Seasonic X-Series X-660
- Betriebssystem
- Microsoft Windows 10 Professional 64bit
- Webbrowser
- Mozilla Firefox
- Verschiedenes
- Watercool HTF2 Dual + 2x Papst 4412 F/2GL
oh danke vielmals!
geht nun auch mit scanf()
geht nun auch mit scanf()
\²³/
Grand Admiral Special
Eine if-"Schleife" will - glaube ich - niemand. If-Anweisungen sind keine Schleifen, weil sich der Code nicht wiederholt.Jetzt ist mein Problem, dass er meine if-schleife nicht will,
So sehe das Ganze in C++ aus:
Das "using namespace std;" sollte möglichst auch vermieden werden, das "Entblößen" eines ganzen Namespaces generell spricht etwas gegen die Idee dahinter, besonders wenn man es mit solch großen Varianten macht. Stattdessen sollte man sich die Zeit nehmen und wirklich jedes mal die mit Hilfe des Scope-Operators ( :: ) die jeweilige Funktionalität heraussuchen. Alternativ für Schreibfaule gibt es den Zwischenweg mit "using std::cout;" ect. für häufig genutze Sachen.
Ich bin sehr darüber überrascht, dass ihr ausschließlich mit stdio.h arbeitet, eine C Bibliothek in einem C++ Kurs.
C++ hat eigentlich gar keine .h Endungen bei Headerdateien und auch Funktionen wie printf oder scanf sind reine C Funktionen und haben in einem frisch aufgelegten C++ Programm nichts zu suchen. Mir fällt auch die Initialisierung der lokalen Variablen jeweils am Anfang einer Scope auf, typisch für C Code und gilt als schlechter Stil für C++ Programme.
Vielleicht sollte euer Professor korrekterweise den Kurs einfach in C - Kurs umbennen.
Code:
#include <cmath>
#include <iostream>
#include <sstream>
using namespace std;
const float PI = 3.141592654f;
int main()
{
const float e = PI/6.0f;
cout << "Für Bogenmass bitte '0' eingeben. Sonst Ausgabe in Grad.\n";
int user_input;
cin >> user_input;
stringstream ss;
ss << user_input;
int user_choice;
ss >> user_choice;
if ( ss.fail() || user_choice != 0 )
{
cout << "Ausgabe von Cos(x) in Grad\n";
float current = 0;
for ( int i = 0; i <= 12; ++i )
{
cout << cos(current) << "\n";
current += 30.0f;
}
}
else
{
cout << "Ausgabe von Cos(x) im Bogenmass\n";
float current = 0;
for ( int i = 0; i <= 12; ++i )
{
cout << cos(current) << "\n";
current += e;
}
}
return 0;
}
Das "using namespace std;" sollte möglichst auch vermieden werden, das "Entblößen" eines ganzen Namespaces generell spricht etwas gegen die Idee dahinter, besonders wenn man es mit solch großen Varianten macht. Stattdessen sollte man sich die Zeit nehmen und wirklich jedes mal die mit Hilfe des Scope-Operators ( :: ) die jeweilige Funktionalität heraussuchen. Alternativ für Schreibfaule gibt es den Zwischenweg mit "using std::cout;" ect. für häufig genutze Sachen.
Ich bin sehr darüber überrascht, dass ihr ausschließlich mit stdio.h arbeitet, eine C Bibliothek in einem C++ Kurs.
C++ hat eigentlich gar keine .h Endungen bei Headerdateien und auch Funktionen wie printf oder scanf sind reine C Funktionen und haben in einem frisch aufgelegten C++ Programm nichts zu suchen. Mir fällt auch die Initialisierung der lokalen Variablen jeweils am Anfang einer Scope auf, typisch für C Code und gilt als schlechter Stil für C++ Programme.
Vielleicht sollte euer Professor korrekterweise den Kurs einfach in C - Kurs umbennen.
Zuletzt bearbeitet:
also ich würde das Programm auch neu aufsetzen
das ist bis auf cin und Kleinigkeiten alles Ansi-C
was lernt ihr also wirklich?
C oder C++ ?
auch mal so aus Neugier
welchen Compiler benutzt ihr?
ich habe z.B. festgestellt, das math.h bei mir zu Hause mit gcc M_PI definiert hat, Visual Studio (wird so vom Prof und uns verlangt) aber nicht
bei C++ bin ich noch nicht ganz so weit
bei uns liegt es allerdings daran, das wir 1,5 Semester Ansi C programmiert haben und jetzt auf objektorientierte Programmierung für ein halbes Semester übergehen
da benutzt man einiges erstmal weiter, vorallem wenn man mehr oder weniger selbst alles suchen muß
das Schlimme ist nur, das es bei unseren simplen Programmen gut geht
MfG Micha
das ist bis auf cin und Kleinigkeiten alles Ansi-C
was lernt ihr also wirklich?
C oder C++ ?
auch mal so aus Neugier
welchen Compiler benutzt ihr?
ich habe z.B. festgestellt, das math.h bei mir zu Hause mit gcc M_PI definiert hat, Visual Studio (wird so vom Prof und uns verlangt) aber nicht
bei C++ bin ich noch nicht ganz so weit
das mache ich aber auch so bzw. damit hatte ich auch schon ProblemeMir fällt auch die Initialisierung der lokalen Variablen jeweils am Anfang einer Scope auf, typisch für C Code und gilt als schlechter Stil für C++ Programme.
bei uns liegt es allerdings daran, das wir 1,5 Semester Ansi C programmiert haben und jetzt auf objektorientierte Programmierung für ein halbes Semester übergehen
da benutzt man einiges erstmal weiter, vorallem wenn man mehr oder weniger selbst alles suchen muß
das Schlimme ist nur, das es bei unseren simplen Programmen gut geht
MfG Micha
Das Initialisieren der Variablen jeweils am Anfang ist meines Wissens auch nicht so schlimm (gerade für Optimierungen hat das bei modernen Kompiler kaum Auswirkungen, die sind mittlerweile clever genug), soll nur Zwecks Übersicht anders geregelt werden, was für Einige die gegenteilige Wirkung zu haben scheint.
Es könnte jedoch ein weiterer Hinweis darauf sein, dass da eigentlich C gelehrt wird.
Gerade in den For-Schleifen sieht es auffällig aus, da soweit ich mich erinnern kann in C die Initialisierung des schleifen-lokalen Zählers innerhalb des Schleifenkopfes nicht gültig ist, aber bei C++ standardmäßig praktiziert wird.
Es könnte jedoch ein weiterer Hinweis darauf sein, dass da eigentlich C gelehrt wird.
Gerade in den For-Schleifen sieht es auffällig aus, da soweit ich mich erinnern kann in C die Initialisierung des schleifen-lokalen Zählers innerhalb des Schleifenkopfes nicht gültig ist, aber bei C++ standardmäßig praktiziert wird.
Zuletzt bearbeitet:
kannst du mal bitte ganz kurz schreiben wie "Hello World" damit aussieht?Das "using namespace std;" sollte möglichst auch vermieden werden, das "Entblößen" eines ganzen Namespaces generell spricht etwas gegen die Idee dahinter, besonders wenn man es mit solch großen Varianten macht. Stattdessen sollte man sich die Zeit nehmen und wirklich jedes mal die mit Hilfe des Scope-Operators ( :: ) die jeweilige Funktionalität heraussuchen. Alternativ für Schreibfaule gibt es den Zwischenweg mit "using std::cout;" ect. für häufig genutze Sachen.
also ohne "using namespace std"
man findet bei den ersten paar Google Treffern nur mit
wir benutzen das zur Zeit auch noch (sicher um uns bei der ersten Aufgabe in C++ nicht total zu verwirren)
ich meine das auch nicht für die Variablen, sondern allgemeinDas Initialisieren der Variablen jeweils am Anfang ist meines Wissens auch nicht so schlimm (gerade für Optimierungen hat das bei modernen Kompiler kaum Auswirkungen, die sind mittlerweile clever genug), soll nur Zwecks Übersicht anders geregelt werden, was für Einige die gegenteilige Wirkung zu haben scheint.
in der jetzigen Aufgabe habe ich auch erstmal math.h weiterverwendet, war Wurzel oder so gefordert und das die in C++ cmath habe ich halt erst später mitbekommen usw.
ich gehe mal stark davon ausEs könnte jedoch ein weiterer Hinweis darauf sein, dass da eigentlich C gelehrt wird.
das was du geschrieben hast sieht für mich noch wegen den "cout<<" etwas "unbekannt" aus, aber das was p4z1f1st geschrieben hat, ist mir sehr vertraut
ganz, ganz früher hatte ich java und auch wenn ich davon nichts mehr wußte, die for-Schleifen haben anfangs bei mir nicht funktionieren wollenGerade in den For-Schleifen sieht es auffällig aus, da soweit ich mich erinnern kann in C die Initialisierung des schleifen-lokalen Zählers innerhalb des Schleifenkopfes nicht gültig ist, aber bei C++ standardmäßig praktiziert wird.
nur jetzt im 2. Semester mit C kann ich nicht mehr anders und initialisiere auch bei C++ gleich
MfG Micha
Fonce
Vice Admiral Special
- Mitglied seit
- 03.08.2005
- Beiträge
- 620
- Renomée
- 1
- Prozessor
- AMD Phenom II X3 720BE
- Mainboard
- ASRock AOD790GX/128M
- Kühlung
- Noctua NH-U9F
- Speicher
- 4x1024MB DDR2-800 CL5
- Grafikprozessor
- Radeon HD 4850 512MB@650/1030MHz
- Display
- BenQ FP91GX
- HDD
- Samsung HD753LJ
- Optisches Laufwerk
- Samsung SH-S223F/BEBE
- Gehäuse
- Antec Three Hundred
- Netzteil
- Enermax 460W
- Betriebssystem
- Windows Vista Ultimate 64bit
- Webbrowser
- Firefox
ein Tipp zur Übersicht würde ich die Variablendeklaration immer am anfang der main Funktion vornehmen
das erleichtert anderen deinen Code zu lesen
ich frage mich auch was es füreinen sinn hat die eingabe über die Variable user_input aber in der if Anweisung die variable user_choice zu benutzen
der inhalt beider müsste doch gleich seinn oder etwa nicht?
die Addition der Variablen "current" kann auch in im schleifenkopf vorgenommen werden was die Lesbarkit eigentlich auch verbessern sollte.
achja das f hinter den werten der float variablen kannst du auch weglassen
das ganze würde dann so aussehen
das erleichtert anderen deinen Code zu lesen
ich frage mich auch was es füreinen sinn hat die eingabe über die Variable user_input aber in der if Anweisung die variable user_choice zu benutzen
der inhalt beider müsste doch gleich seinn oder etwa nicht?
die Addition der Variablen "current" kann auch in im schleifenkopf vorgenommen werden was die Lesbarkit eigentlich auch verbessern sollte.
achja das f hinter den werten der float variablen kannst du auch weglassen
das ganze würde dann so aussehen
Code:
#include <cmath>
#include <iostream>
#include <sstream>
using namespace std;
const float PI = 3.141592654;
int main()
{
const float e=PI/6.0;
int user_input;
float current=0;
stringstream ss;
cout << "Für Bogenmass bitte '0' eingeben. Sonst Ausgabe in Grad.\n";
cin >> user_input;
ss << user_input;
if(ss.fail() || user_input!=0)
{
cout << "Ausgabe von Cos(x) in Grad\n";
for(int i=0; i<=12; ++i,current+=30)
{
cout << cos(current) << "\n";
}
}
else
{
cout << "Ausgabe von Cos(x) im Bogenmass\n";
for(int i=0; i<=12; ++i, current+=e)
{
cout << cos(current) << "\n";
}
}
return 0;
}
Zuletzt bearbeitet:
Nachtschicht
Admiral Special
Jo, so hat man das vor 15 Jahren gemachtein Tipp zur Übersicht würde ich die Variablendeklaration immer am anfang der main Funktion vornehmen
Der Sinn der Definition "on the fly" ist, dass eine Variable erst definiert wird, wenn sie auch benötigt wird. Es kann sein, dass das Programm vorher anders verzweigt und die ganze Definition sinnlos war. Selbst, wenn nicht gleichzeitig noch eine aufwändige Initialisierung der Variable stattfindet und man somit den Laufzeitvorteil vernachlässigen kann, so erhöht sich doch die Lesbarkeit.
Migmicha hat die Frage gestellt, wie denn "Hello world" ohne "using namespace std" aussieht, na etwa so:
std::cout << "Hello World" << std::endl;
p4z1f1st
Grand Admiral Special
- Mitglied seit
- 28.04.2003
- Beiträge
- 9.722
- Renomée
- 81
- Prozessor
- AMD FX-6300
- Mainboard
- Gigabyte GA-970A-UD3
- Kühlung
- HEATKILLER® CPU Rev3.0 LC + HEATKILLER® GPU-X² 69x0 LT
- Speicher
- 2x 4096 MB G.Skill RipJawsX DDR3-1600 CL7
- Grafikprozessor
- AMD Radeon RX 480 8GB
- Display
- Dell U2312HM
- HDD
- Crucial m4 SSD 256GB
- Optisches Laufwerk
- Sony Optiarc AD-7260S
- Soundkarte
- Creative Labs SB Audigy 2 ZS
- Gehäuse
- Chieftec Scorpio TA-10B-D (BxHxT: 205x660x470mm)
- Netzteil
- Seasonic X-Series X-660
- Betriebssystem
- Microsoft Windows 10 Professional 64bit
- Webbrowser
- Mozilla Firefox
- Verschiedenes
- Watercool HTF2 Dual + 2x Papst 4412 F/2GL
Ok, nach eMail-Abfrage des Profs, lernen wir doch "nur" rein C - wir benutzen nur Visual C++ als Kompiler.
Fonce
Vice Admiral Special
- Mitglied seit
- 03.08.2005
- Beiträge
- 620
- Renomée
- 1
- Prozessor
- AMD Phenom II X3 720BE
- Mainboard
- ASRock AOD790GX/128M
- Kühlung
- Noctua NH-U9F
- Speicher
- 4x1024MB DDR2-800 CL5
- Grafikprozessor
- Radeon HD 4850 512MB@650/1030MHz
- Display
- BenQ FP91GX
- HDD
- Samsung HD753LJ
- Optisches Laufwerk
- Samsung SH-S223F/BEBE
- Gehäuse
- Antec Three Hundred
- Netzteil
- Enermax 460W
- Betriebssystem
- Windows Vista Ultimate 64bit
- Webbrowser
- Firefox
wenn verzweigungen dazukommen gut dann muss ich dir zustimmmen aber wenn wie bei diesem Programm alle Variablen auch wirklich genutz werden welchen performance vorteil soll es dann bringen die Variablen "on the fly" zu deklarieren?Jo, so hat man das vor 15 Jahren gemacht
Der Sinn der Definition "on the fly" ist, dass eine Variable erst definiert wird, wenn sie auch benötigt wird. Es kann sein, dass das Programm vorher anders verzweigt und die ganze Definition sinnlos war. Selbst, wenn nicht gleichzeitig noch eine aufwändige Initialisierung der Variable stattfindet und man somit den Laufzeitvorteil vernachlässigen kann, so erhöht sich doch die Lesbarkeit.
Migmicha hat die Frage gestellt, wie denn "Hello world" ohne "using namespace std" aussieht, na etwa so:
std::cout << "Hello World" << std::endl;
nach meinem empfinden erhöht es auch nicht die lesbarkeit der Codes wenn man wie eamC die variable ss erst vor der eingabe deklariert.
insbesondere bei for-Schleifen erhöht das den Komfort
bei C schreibt man die Schleife und muß erstmal an den Anfang des Unterprogramms um eine neue Variable zu deklarieren
bei C++ und Java schreibt man einfach for(int i=0;...;...)
die Variable ist auch nur innerhalb der Schleife gültig
damit kann man sie danach nochmal neu deklarieren bzw. eine vorher schon verwendete Variable bleibt erhalten
die in der Schleife ist eine andere Variable
um das zu verdeutlichen, was ich meine:
bei C geht das nicht
um das selbe zu erreichen müßte man zwei Variablen definieren, eine für die Schleife und eine Außerhalb
@Nachtschicht
danke, ergibt langsam einen Sinn für mich
MfG Micha
bei C schreibt man die Schleife und muß erstmal an den Anfang des Unterprogramms um eine neue Variable zu deklarieren
bei C++ und Java schreibt man einfach for(int i=0;...;...)
die Variable ist auch nur innerhalb der Schleife gültig
damit kann man sie danach nochmal neu deklarieren bzw. eine vorher schon verwendete Variable bleibt erhalten
die in der Schleife ist eine andere Variable
um das zu verdeutlichen, was ich meine:
Code:
#include <iostream>
int main() {
int i=1;
for(int i=0;i<=5;i++)
std::cout << " Wert in der Schleife i= "<< i << std::endl;
std::cout << " Wert ausserhalb i= "<< i << std::endl;
std::cout <<"\n"<<std::endl;
return 0;
}
Wert in der Schleife i= 0
Wert in der Schleife i= 1
Wert in der Schleife i= 2
Wert in der Schleife i= 3
Wert in der Schleife i= 4
Wert in der Schleife i= 5
Wert ausserhalb i= 1
bei C geht das nicht
um das selbe zu erreichen müßte man zwei Variablen definieren, eine für die Schleife und eine Außerhalb
@Nachtschicht
danke, ergibt langsam einen Sinn für mich
MfG Micha
Zuletzt bearbeitet:
Fonce
Vice Admiral Special
- Mitglied seit
- 03.08.2005
- Beiträge
- 620
- Renomée
- 1
- Prozessor
- AMD Phenom II X3 720BE
- Mainboard
- ASRock AOD790GX/128M
- Kühlung
- Noctua NH-U9F
- Speicher
- 4x1024MB DDR2-800 CL5
- Grafikprozessor
- Radeon HD 4850 512MB@650/1030MHz
- Display
- BenQ FP91GX
- HDD
- Samsung HD753LJ
- Optisches Laufwerk
- Samsung SH-S223F/BEBE
- Gehäuse
- Antec Three Hundred
- Netzteil
- Enermax 460W
- Betriebssystem
- Windows Vista Ultimate 64bit
- Webbrowser
- Firefox
klar geht das bei C
zumindest unte rLinux mit gcc als Compiler gibt es da keine Probleme
das man die Zählvariablen der Schleife im Schleifenkopf deklariert und zuweisst ist aber auch nichts aussergewöhnliches und dem habe ich auch nicht wiedersprochen
zumindest unte rLinux mit gcc als Compiler gibt es da keine Probleme
das man die Zählvariablen der Schleife im Schleifenkopf deklariert und zuweisst ist aber auch nichts aussergewöhnliches und dem habe ich auch nicht wiedersprochen
Code:
#include <stdio.h>
int main(){
int i=1; // im zweiten Versuch auskommentiert
for(int i=0;i<=5;i++)
printf("innen: %d \n",i);
printf("aussen: %d \n",i);
// getchar();
printf("\n\n");
return 0;
}
gcc Hallo.c
Hallo.c: In function ‘main’:
Hallo.c:8: error: redefinition of ‘i’
Hallo.c:6: error: previous definition of ‘i’ was here
Hallo.c:8: error: ‘for’ loop initial declaration used outside C99 mode
gcc4.1 Ubuntu Edgy Eft
wäre auch nicht nach Ansi C korrekt, wenn es doch funktioniert hätte
selbst wenn man die erste Initialisierung weglässt
gcc Hallo.c
Hallo.c: In function ‘main’:
Hallo.c:5: error: ‘for’ loop initial declaration used outside C99 mode
wir benutzen wie gesagt auch Visual StudioOk, nach eMail-Abfrage des Profs, lernen wir doch "nur" rein C - wir benutzen nur Visual C++ als Kompiler.
da muß man die Quelltexte immer unter *.c abspeichern und schon wird der interne C-Kompiler verwendet
wenn man die Dateien einfach nur mit dem Namen speichert, wird eine *.cpp daraus und beim Kompilieren erhält man 100 Fehlermeldungen
bei deinem Programm hast du noch Glück...
MfG Micha
Wie schon von anderen erwähnt wird wegen Optimierungszwecken (mittlerweile zweitrangig) und der Übersicht wegen gerade das nicht gemacht.ein Tipp zur Übersicht würde ich die Variablendeklaration immer am anfang der main Funktion vornehmen
das erleichtert anderen deinen Code zu lesen
ich frage mich auch was es füreinen sinn hat die eingabe über die Variable user_input aber in der if Anweisung die variable user_choice zu benutzen
der inhalt beider müsste doch gleich seinn oder etwa nicht?
die Addition der Variablen "current" kann auch in im schleifenkopf vorgenommen werden was die Lesbarkit eigentlich auch verbessern sollte.
achja das f hinter den werten der float variablen kannst du auch weglassen
das ganze würde dann so aussehen
Die Variable user_choice habe ich ebenfalls fürs Verständnis eingefügt, man hätte von Stringstream zurück in user_input streamen können, hätte die gleiche Wirkung gehabt.
Das Stringstream ist in diesem Fall eigentlich ganz überflüssig, sollte man sich aber vormerken für spätere Programme, welche die Eingabe auch auf Korrektheit überprüfen sollen.
Das current kann man in den Schleifenkopf stellen, ist denke ich wie bei den Variablendeklerationen Geschmacksache was übersichtlicher wirkt. Ich persönlich habe mir angewöhnt im Schleifenkopf nur die Variablen zu bearbeiten, auf die auch in diesem geprüft wird.
Das f könnte man weglassen, sollte man aber nicht. Eine x.x Zahl wird vom Compiler immer als double interpretiert, dies kann in manchen Fällen zu unerwünschten automatischen Castingvorgängen führen, die vor einem selbst unerkannt bleiben aber besonders in engen Schleifen zu Performanceeinbüßen führen können.
Zuletzt bearbeitet:
wäre auch nicht nach Ansi C korrekt, wenn es doch funktioniert hätte
Nach Ur-ANSI-C nicht, sehr wohl aber nach ISO/IEC 9899:1999 (C99) und sollte sich mit entsprechendem Flag ("-std=c99" [1]) auch kompilieren lassen.
[1] http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/C-Dialect-Options.html#C-Dialect-Options
Nachtschicht
Admiral Special
Na, da habe ich so meine Zweifel, ob das in Bezug auf die Performance zweitrangig ist, an welcher Stelle Variablen definiert werden. Bei einem single-threaded-Programm kann ich mir noch vorstellen, dass ein Compiler eine Variable wirklich erst initialisiert, wenn sie auch benötigt wird. So richtig spannend wird es bei Multithreaded Programmen. Den Compiler möchte ich sehen, der da an all Eventualitäten "denkt" und das Ganze fehlerfrei behandelt. Zumal ja erst der Linker weiß, ob der ganze Krempel ST oder MT ist.Wie schon von anderen erwähnt wird wegen Optimierungszwecken (mittlerweile zweitrangig)
Gibt es dazu Links?
Ein weiterer Aspekt, der für die Definition "on the fly" spricht, ist, dass man möglichst gleich den richtigen Konstruktor aufrufen sollte, dessen Initialisierungswerte womöglich nicht gleich zu Beginn der Methode zu Verfügung stehen, z.B.:
std::string abc; //Konstruktor
abc = "bodo"; //Zuweisungsoperator
ist langsamer als
std::string abc ("bodo"); // nur Konstruktor
ich spreche nunmal deutsch und nicht bayrischNach Ur-ANSI-C nicht, sehr wohl aber nach ISO/IEC 9899:1999 (C99) und sollte sich mit entsprechendem Flag ("-std=c99" [1]) auch kompilieren lassen.
[1] http://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/C-Dialect-Options.html#C-Dialect-Options
wir lernen Ansi-C und keinen Dialekt und keine Erweiterung, sofern nicht gerade zufällig
MfG Micha
Ein sehr gutes Beispiel.Ein weiterer Aspekt, der für die Definition "on the fly" spricht, ist, dass man möglichst gleich den richtigen Konstruktor aufrufen sollte, dessen Initialisierungswerte womöglich nicht gleich zu Beginn der Methode zu Verfügung stehen, z.B.:
std::string abc; //Konstruktor
abc = "bodo"; //Zuweisungsoperator
ist langsamer als
std::string abc ("bodo"); // nur Konstruktor
Man sieht oft solche Konstruktionen wie "string s = "mein Text";" und auch in diesem Fall würde das Programm zuerst ein String s erzeugen, dann ein weiteres String und dann in diesem besonderen Fall den Copy-Konstruktor aufrufen um den Text s zuzuweisen.
Ähnlich vorgehen sollte man auch wenn man Objekte zurückgeben möchte.
Z.B. "return meinObjekt(meinArgument);"
statt
" meinObjekt x(meinArgument);
return x;".
Zuletzt bearbeitet:
Nachtschicht
Admiral Special
Das ist nun in Bezug auf die Performance wirklich nahezu egal, ob der Speicherbereich, der niemandem gehört oder der Speicherbereich der Variable x zurückgegeben wird. Das sage ich als alter Assemblerprogrammierer In den Firmen gibt es mitunter sogar Coding-Guidelines, die genau diese elegante Methode des "returns" untersagen.Ähnlich vorgehen sollte man auch wenn man Objekte zurückgeben möchte.
Z.B. "return meinObjekt(meinArgument);"
statt
" meinObjekt x(meinArgument);
return x;".
Ich würde oft die umständlichere Variante wählen, denn der Tag wird kommen, an dem man genau an der Stelle mit dem Debugger einen Fehler suchen wird und man wird dankbar sein für jede nicht wegoptimierte Zeile umständlichen Codes
Nun, nach dem Ende der Scope ist der Speicherbereich in beiden Fällen herrenlos.Das ist nun in Bezug auf die Performance wirklich nahezu egal, ob der Speicherbereich, der niemandem gehört oder der Speicherbereich der Variable x zurückgegeben wird. Das sage ich als alter Assemblerprogrammierer In den Firmen gibt es mitunter sogar Coding-Guidelines, die genau diese elegante Methode des "returns" untersagen.
Ich würde oft die umständlichere Variante wählen, denn der Tag wird kommen, an dem man genau an der Stelle mit dem Debugger einen Fehler suchen wird und man wird dankbar sein für jede nicht wegoptimierte Zeile umständlichen Codes
Zwar bin ich kein erfahrener Assemblerprogrammierer, aber als C++ Programmierer sage ich Dir es ist nicht egal in Bezug auf Performance.
Der Begriff "Return-Value Optimization" wurde meines Wissens von Scott Meyers in dem Standardwerk "Effective C++" ans Licht geführt und verdeutlicht welche Optimierungsmöglichkeiten man hat, wenn man Objekte by Value zurückzugeben hat.
Bruce Eckel hat dieses auch in einem weiteren wichtigen C++ Buch aufgegriffen, in "Thinking in C++", somit befinde ich mich auf der sicheren Seite dies zu behaupten 8) .
Kurz gesagt spart man sich einen Konstruktor- und Dekonstruktoraufruf, wenn man den Aufruf direkt beim Return-Statement durchführt, was bei komplexen Objekten immense Geschwindigkeitsvorteile hat.
In vielen Fällen wird der Compiler selbst so eine Funktion umbauen, indem er den Return-Wert als Referenz übergibt, Dein lokales Objekt somit unnötig macht und entfernt.
Diese Arbeit sollte man jedoch selbst übernehmen, das gehört einfach zum guten Ton.
Welche Firmen sich gegen Größen wie Scott Meyers gegenstellen was C++ Programmierung angeht interessiert mich aber nun sehr .
Womögliche arbeiten diese Firmen nicht an performancekritischer Software, das wäre eine logische Erklärung?
Nachtschicht
Admiral Special
Das verstehe ich gerade nicht, wieso wird der Konstruktor- und Destruktoraufruf eingespart, wenn man das Objekt nur auf dem Stack erzeugt und zerstört?Kurz gesagt spart man sich einen Konstruktor- und Dekonstruktoraufruf, wenn man den Aufruf direkt beim Return-Statement durchführt, was bei komplexen Objekten immense Geschwindigkeitsvorteile hat.
Naja, Scotti muß auch seine Bücher verkaufen Ein paar Kollegen hatten einen Kurs bei ihm gewonnen, aber auf die einfache Frage, ob denn seines Wissens C++ in einer sicherheitskritischen Applikation eingesetzt wird (an der Menschenleben hängen), wußte er keine Antwort bzw. konnte kein Beispiel nennen. (Die Alternative ist C, was auch benutzt wird).Welche Firmen sich gegen Größen wie Scott Meyers gegenstellen was C++ Programmierung angeht interessiert mich aber nun sehr .
Womögliche arbeiten diese Firmen nicht an performancekritischer Software, das wäre eine logische Erklärung?
In der Praxis sind Zuverlässigkeit, Reproduzierbarkeit, etc. allemal wichtiger als minimale Performancevorteile in womöglich völlig unwichtigen Codeteilen, die selten durchlaufen werden.
"return meinObjekt(meinArgument);"
statt
" meinObjekt x(meinArgument);
return x;".
solange man keine Debug-builds an Kunden ausliefert, sind beide Versionen gleich schnell (RVO)
aber nur weil die Implementierung von std::string() nicht trivial ist. Sonst wird das auch wegoptimiert.std::string abc; //Konstruktor
abc = "bodo"; //Zuweisungsoperator
ist langsamer als
std::string abc ("bodo"); // nur Konstruktor
Das war mir Anfangs auch nicht klar. Meine Folgerung aus der Compileroptimierung war, dass das Return Objekt so bereits die Referenz ist des Objektes welches das Return Statement erwartet, also in etwa so:Das verstehe ich gerade nicht, wieso wird der Konstruktor- und Destruktoraufruf eingespart, wenn man das Objekt nur auf dem Stack erzeugt und zerstört?
Code:
MyClass myObject = getMyObject();
...
MyClass getMyObject()
{
MyClass tempObject;
return tempObject;
}
Wird vom Compiler in Folgendes optimiert:
Code:
void getMyObject( MyClass& _returnRef )
{
_returnRef = MyClass();
return;
}
Somit fällt der Konstruktor- und Dekonstruktoraufruf von tempObject aus.
Mit dem Umschreiben in return MyClass(); kommt man ledeglich dem Compiler entgegen dh. das Return Statement wird direkt in den Assigment Parameter genommen.
Stimme Dir da natürlich zu, jedoch bleibt die Aussage korrekt, dass es Performancevorteile dadurch gibt, und in diesem Fall verliert man kaum an Leserlichkeit oder Stabilität. Was das Debuggen angeht, das Return Objekt wird ja dem erwartenden Objekt gleichgesetzt, deswegen verstehe ich nicht ganz den Nachteil wenn man es so schreibt.In der Praxis sind Zuverlässigkeit, Reproduzierbarkeit, etc. allemal wichtiger als minimale Performancevorteile in womöglich völlig unwichtigen Codeteilen, die selten durchlaufen werden.
Zuletzt bearbeitet:
Ähnliche Themen
- Antworten
- 3
- Aufrufe
- 7K