 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Andreas Schmidt Guest
|
Posted: Fri Oct 15, 2004 9:16 am Post subject: simple for Schleife will nicht arbeiten |
|
|
Hallo NG,
mein Schreibtisch hat schon arg viele Bißspuren, da ich schlich nicht sehe,
was an meiner Routine falsch ist.
Folgendes: Ich habe vor ein paar Jahren in einer NG für VB Programmierung
ein Routine gefunden, die 2 Stringwerte vergleicht und einen
Ähnlichkeitsindex ausspuckt. Ich empfand sie als Besser gegenüber den
Standard Routinen zu soundex, levenshtein etc.
Diese Routine werkelt seit dem auch in einem VBA Projekt super vor sich
hin.
Nun wollte ich das ganze in C++ umsetzen (ich versuche gerade diese Sprache
zu lernen) und stoße dabei auf ein Problem.
Hier mal der Quelltext:
int CalcSimilarity(char *cS1, char *cS2)
{
unsigned int iDist = 0, iK = 0, iJ = 0, iI = 0, iLastI = 0;
int iFsum = 0, iSum = 0, iResult = 0;
bool bFound, bBreak;
unsigned int iB1, iB2;
iB1 = (int) strlen(cS1) - 1;
iB2 = (int) strlen(cS2) - 1;
for (iDist = 0; iDist <= iB1 - 1; iDist++)
{
for (iK = 0; iK <= iB1 - iDist; iK++)
{
bFound = false;
printf("JJJJJ: %in", iJ);
for (iJ = 0; iJ <= iB2 - iDist; iJ++);
{
bBreak = false;
printf("k:%i, j:%in", iK, iJ);
<--- Hier steht noch anderer Quelltext, der aber mit dem Fehler nix zu tun
hat --->
}
if (bFound)
{
iSum += iDist + iDist + 2;
} else {
iSum += iDist;
iFsum -= 1;
}
iLastI = 0;
}
printf("%i - %in", iFsum, iSum);
}
<--- Hier steht noch anderer Quelltext, der aber mit dem Fehler nix zu tun
hat --->
return iResult;
}
Die printf Anweisungen habe ich erst mal nur dazwischen geknallt, um mir
mal die Werte meiner Variablen anzuzeigen.
Und dabei bin ich auf das Problem auch aufmerksam geworden. In der dritten
for Schleife verwende ich die Variable iJ zum hochzählen ... begonnen
werden soll dabei (wie bei den anderen auch) mit 0. Nur, hat komischerweise
bereits zu beginn der Schleife iJ einen Wert, der die Länge des zu erst
übergebenen Stringwertes (welche in iB2 festgehalten wird). Vielleicht noch
eines ... es wird als cS2 immer der längere von beiden Strings übergeben.
Warum beginnt iJ nicht mit 0?? An keiner anderen Stelle wird iJ verändert.
Hoffe ihr könnt helfen!!!
Danke schon mal.
Bye
Andreas
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Maximilian Hrabowski Guest
|
Posted: Fri Oct 15, 2004 12:18 pm Post subject: Re: simple for Schleife will nicht arbeiten |
|
|
Hallo,
zuerst ein paar Anmerkungen:
- Du willst const char* anstatt char* an deine Methode übergeben. Das verhindert, dass Du ausversehen Deine strings veränderst.
- Vielleicht willst Du lieber gleich auf char* verszichten und mit std::string arbeiten
- Anstatt printf verwendet man bei C++ die Ausgabe Streams. Also statt z.B. printf("%in",i) lieber std::cout << i << std::endl;
(#include
| Quote: |
int CalcSimilarity(char *cS1, char *cS2)
{
unsigned int iDist = 0, iK = 0, iJ = 0, iI = 0, iLastI = 0;
int iFsum = 0, iSum = 0, iResult = 0;
bool bFound, bBreak;
unsigned int iB1, iB2;
iB1 = (int) strlen(cS1) - 1;
iB2 = (int) strlen(cS2) - 1;
for (iDist = 0; iDist <= iB1 - 1; iDist++)
{
for (iK = 0; iK <= iB1 - iDist; iK++)
{
bFound = false;
printf("JJJJJ: %in", iJ);
for (iJ = 0; iJ <= iB2 - iDist; iJ++);
|
generell empfiehlt es sich eine variable erst dann zu definieren wenn Du sie brauchst. In Deinem Fall also
for( int iJ=0; iJ<= iB2- iDist; iJ++ )
genauso mit den anderen Variablen.
Dein Problem könnte mit dem Semikolon direkt hinter besagtem Schleifenkopf zusammen hängen. Das Semikolon bewirkt dass es sich
hierbei um eine Schleife mit leerem Anweisungsblock handelt.
Gruß,
Maxim
| Quote: | {
bBreak = false;
printf("k:%i, j:%in", iK, iJ);
--- Hier steht noch anderer Quelltext, der aber mit dem Fehler nix zu tun
hat ---
}
if (bFound)
{
iSum += iDist + iDist + 2;
} else {
iSum += iDist;
iFsum -= 1;
}
iLastI = 0;
}
printf("%i - %in", iFsum, iSum);
}
--- Hier steht noch anderer Quelltext, der aber mit dem Fehler nix zu tun
hat ---
return iResult;
}
Die printf Anweisungen habe ich erst mal nur dazwischen geknallt, um mir
mal die Werte meiner Variablen anzuzeigen.
Und dabei bin ich auf das Problem auch aufmerksam geworden. In der dritten
for Schleife verwende ich die Variable iJ zum hochzählen ... begonnen
werden soll dabei (wie bei den anderen auch) mit 0. Nur, hat komischerweise
bereits zu beginn der Schleife iJ einen Wert, der die Länge des zu erst
übergebenen Stringwertes (welche in iB2 festgehalten wird). Vielleicht noch
eines ... es wird als cS2 immer der längere von beiden Strings übergeben.
Warum beginnt iJ nicht mit 0?? An keiner anderen Stelle wird iJ verändert.
Hoffe ihr könnt helfen!!!
Danke schon mal.
Bye
Andreas
|
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Michael Karcher Guest
|
Posted: Fri Oct 15, 2004 12:29 pm Post subject: Re: simple for Schleife will nicht arbeiten |
|
|
Andreas Schmidt <nospaming (AT) online (DOT) de> wrote:
| Quote: | for (iJ = 0; iJ <= iB2 - iDist; iJ++);
^ Oops!
{
bBreak = false;
printf("k:%i, j:%in", iK, iJ);
for Schleife verwende ich die Variable iJ zum hochzählen ... begonnen
werden soll dabei (wie bei den anderen auch) mit 0.
|
Das tut es auch, aber die Schleife besteht aus der Leeranweisung ";", wenn
die Schleife durchgelaufen ist, sollte iJ = iB2-iDist+1 sein, und mit dem
Wert wird dann der Block dahinter ausgeführt.
Michael Karcher
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Malte Starostik Guest
|
Posted: Sat Oct 16, 2004 5:02 pm Post subject: Re: simple for Schleife will nicht arbeiten |
|
|
Andreas Schmidt schrieb:
| Quote: | Nun wollte ich das ganze in C++ umsetzen (ich versuche gerade diese Sprache
zu lernen) und stoße dabei auf ein Problem.
|
Dein eigentliches Problem wurde ja schon beantwortet, aufgrund des
obigen Satzes noch ein paar Anmerkungen, bitte nicht übelnehmen:
| Quote: | Hier mal der Quelltext:
int CalcSimilarity(char *cS1, char *cS2)
|
Wie Maximilian bereits gesagt hat, sollten cS1 und cS2 auf jeden Fall
const sein, da CalcSimilarity sie nicht verändert, noch besser
std::string statt C-Strings.
| Quote: | {
unsigned int iDist = 0, iK = 0, iJ = 0, iI = 0, iLastI = 0;
int iFsum = 0, iSum = 0, iResult = 0;
bool bFound, bBreak;
unsigned int iB1, iB2;
|
Solche Mammut-Deklarationen am Anfang einer Funktion sind erforderlich
in C. In C++ sind sie unnötig. Variablen sollten beim ersten Gebrauch
deklariert werden, dann wird auch der Hungarian-Notation-Präfix (i for
int, b vor bool etc.) überflüssig. Diese Präfixe können zwar theoretisch
helfen, da man nicht zurückscrollen muß, um zu sehen, was für eine
Variable iDist ist, sagen aber z.B. nichts über deren initalen Wert aus.
Wenn eine Variable später im Typ geändert wird, muß ihr Name an allen
Vorkommen mitgeändert werden oder es entstehen Diskrepanzen, wie hier
bereits eine existiert: iDist, iK, iJ, iI, iLastI, iB1 und iB2 sehen vom
Präfix her nach ints aus, sind aber unsigned ints! Sie sind einfach
unschön (okay, das ist Geschmackssache). Variablennamen sollten eine
Aussage über die Funktion der Variablen beinhalten, der Typ ist bereits
aus der Deklaration ersichtlich und die ist immer leicht zu finden, wenn
sie sich kurz vor dem Gebrauch befindet.
Grundsätzlich sollten einbuchstabige Variablennamen vermieden werden
(und im Grunde ist auch iJ ein solcher, das i ist ja nur bereits
erwähnter Präfix). i als Schleifenzähler ist üblich, wenn zu viele
verschachtelte Schleifen und damit j, k, ... nötig werden, ist das
oftmals ein Zeichen schlecht strukturierten Codes.
| Quote: |
iB1 = (int) strlen(cS1) - 1;
iB2 = (int) strlen(cS2) - 1;
|
Dies sind C-Style-Casts. Besserer C++-Stil wäre (inkl. Deklaration, nach
Entfernen selbiger aus den vorangehenden Zeilen):
int iB1 = int(strlen(cS1)) - 1;
iB1 und iB2 (B wie Länge? sind vom Typ unsigned int. Wenn z.B.
strlen(cS1) 0 ist, ist iB1 unsigned(-1), also eine sehr hohe positive
Zahl. Da hilft auch der zwischenzeitliche Cast nichts.
Soll das letzte Zeichen wirklich ignoriert werden (- 1), oder ist das
ein Fehler beim Übersetzen von VB (dessen String-Behandlung ich nicht
kenne)?
| Quote: |
for (iDist = 0; iDist <= iB1 - 1; iDist++)
|
Warum "iDist <= iB1 - 1"? "iDist < iB1" ist leserlicher.
Statt iDist++ ist ++iDist vorzuziehen, da billiger. Macht bei int nichts
aus, bei Iteratoren z.B. schon, da die Postfix-Variante eine hier
unnötige temporäre Kopie erstellt.
Im Falle von strlen(cS1) == 0 wird diese Schleife z.B. auf einem System
mit 32-bittigen ints 4294967295 mal ausgeführt (s.o.)
| Quote: | {
for (iK = 0; iK <= iB1 - iDist; iK++)
{
bFound = false;
printf("JJJJJ: %in", iJ);
|
Besserer C++-Stil mit Typsicherheit unter Verhinderung von Problemen mit
Diskrepanzen zwischen dem %i und dem Typ von iJ:
std::cout << "JJJJJ: " << iJ << std::endl;
| Quote: | for (iJ = 0; iJ <= iB2 - iDist; iJ++);
|
Wie bereits in den anderen Antworten gefunden: diese for-Schleife hat
einen leeren Anweisungsteil. Dies ist übrigens ein Nachteil der
Deklaration von iJ gleich am Anfang der Funktion. Mit diesem Konstrukt:
for (unsigned int iJ = 0; iJ < iB2 - iDist; ++iJ);
wäre der Fehler sofort aufgefallen, da dann im folgenden Block iJ nicht
mehr definiert wäre.
Schön' Gruß,
Malte
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Olaf Krzikalla Guest
|
Posted: Mon Oct 18, 2004 1:09 pm Post subject: Re: simple for Schleife will nicht arbeiten |
|
|
Hi,
Andreas Schmidt schrieb:
| Quote: | Die printf Anweisungen habe ich erst mal nur dazwischen geknallt, um mir
mal die Werte meiner Variablen anzuzeigen.
In Anlehnung an ein Sprichwort: den Fisch hast Du ja nun schon bekommen. |
Aber eigentlich fehlt Dir die Angel - mit einem Debugger hättest Du den
Fehler schnell selbst gefunden. Deswegen: besorge Dir einen Debugger
bzw. lerne den Umgang mit dem für Deinen Compiler mitgelieferten
Debugger. Variablenwerte läßt man sich während der Entwicklung nicht
durch irgendwohin geschriebene Ausgabestatements anzeigen, man schaut
sie sich im Debugger an.
MfG
Olaf Krzikalla
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Axel Panning Guest
|
Posted: Mon Oct 18, 2004 3:05 pm Post subject: Re: simple for Schleife will nicht arbeiten |
|
|
| Quote: |
for (iDist = 0; iDist <= iB1 - 1; iDist++)
Warum "iDist <= iB1 - 1"? "iDist < iB1" ist leserlicher.
Statt iDist++ ist ++iDist vorzuziehen, da billiger. Macht bei int nichts
aus, bei Iteratoren z.B. schon, da die Postfix-Variante eine hier
unnötige temporäre Kopie erstellt.
|
verstehe ich das richtig?
vector
//fülle mit irgendwas
for ( it;it!=myvector.end();++it){
//irgendwas
}
ist schneller als
for ( it;it!=myvector.end();it++){
//irgendwas
}
wie handle ich dann das erste element ab?
it=myvector.begin()-1; dürfte wohl blödsinn ergeben oder?
gruß axel
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Martin Krause Guest
|
Posted: Mon Oct 18, 2004 6:01 pm Post subject: Re: simple for Schleife will nicht arbeiten |
|
|
Hllo Axel,
Axel Panning <axel (AT) harnackstrasse (DOT) de> wrote:
| Quote: |
for (iDist = 0; iDist <= iB1 - 1; iDist++)
Warum "iDist <= iB1 - 1"? "iDist < iB1" ist leserlicher.
Statt iDist++ ist ++iDist vorzuziehen, da billiger. Macht bei int nichts
aus, bei Iteratoren z.B. schon, da die Postfix-Variante eine hier
unnötige temporäre Kopie erstellt.
verstehe ich das richtig?
vector
vector<anyclass
//fülle mit irgendwas
for ( it;it!=myvector.end();++it){
for ( vector |
it!=myvector.end();++it){
| Quote: | //irgendwas
}
ist schneller als
for ( it;it!=myvector.end();it++){
//irgendwas
}
|
Ja, die formale Syntax lautet
for (Initial-Value, Condition, Progress)
und der Prefix-operator ++ braucht keine Kopie des Iterators.
| Quote: | wie handle ich dann das erste element ab?
Das ist der initial-Value für den ersten Durchlauf |
| Quote: | it=myvector.begin()-1; dürfte wohl blödsinn ergeben oder?
|
Genau.
Gruß
Martin
--
------------------- Martin Krause ----------------------------
email: [email]mkr-dr350 (AT) telda (DOT) net[/email] | DRZ 400S
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Thomas Maeder Guest
|
Posted: Mon Oct 18, 2004 6:31 pm Post subject: Re: simple for Schleife will nicht arbeiten |
|
|
Axel Panning <axel (AT) harnackstrasse (DOT) de> writes:
| Quote: | verstehe ich das richtig?
vector<anyclass>::iterator it=myvector.begin();
//fülle mit irgendwas
for ( it;it!=myvector.end();++it){
//irgendwas
}
ist schneller als
for ( it;it!=myvector.end();it++){
//irgendwas
}
|
Das Potential ist da, aber ich würde nachmessen.
| Quote: | wie handle ich dann das erste element ab?
|
*it
| Quote: | it=myvector.begin()-1; dürfte wohl blödsinn ergeben oder?
|
Das hat undefiniertes Verhalten - aber warum meinst Du, dass Du das brauchst?
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Thomas Mang Guest
|
Posted: Mon Oct 18, 2004 6:57 pm Post subject: Re: simple for Schleife will nicht arbeiten |
|
|
"Martin Krause" <mkr-dr350 (AT) telda (DOT) net> schrieb im Newsbeitrag
news:5o08n09uu1r235jnjpkdo4u9907k1aajjk (AT) news (DOT) dirtbike.dns2go.com...
| Quote: | Hllo Axel,
Axel Panning <axel (AT) harnackstrasse (DOT) de> wrote:
for (iDist = 0; iDist <= iB1 - 1; iDist++)
Warum "iDist <= iB1 - 1"? "iDist < iB1" ist leserlicher.
Statt iDist++ ist ++iDist vorzuziehen, da billiger. Macht bei int
nichts
aus, bei Iteratoren z.B. schon, da die Postfix-Variante eine hier
unnötige temporäre Kopie erstellt.
verstehe ich das richtig?
vector
vector<anyclass
//fülle mit irgendwas
for ( it;it!=myvector.end();++it){
for ( vector
it!=myvector.end ++it){
//irgendwas
}
|
Da hast Du 2 Klammern nach 'end' und ein Semikolon vergessen.
| Quote: |
ist schneller als
for ( it;it!=myvector.end();it++){
//irgendwas
}
Ja,
|
Noch schneller ist es, den End-Iterator zu speichern. Dann muß nicht jedes
mal die Funktion aufgerufen werden und der Iterator kopiert werden (Hängt
natürlich vom Typ des iterators und den Optimierungs-möglichkeiten des
Compilers ab).
Außerdem kann man wieder die Funktionsstil-Initialisierung verwenden, was
bei komplexen iterator-Klassen und dummen Compilern eine weitere Kopie
spart:
for (std::vector<anyclass>::iterator It(myvector.begin()),
End(myvector.end());
It != End; ++It)
{
// blah
}
Natürlich sollte man, falls möglich, const_iterator verwenden.
Thomas
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Olaf Krzikalla Guest
|
Posted: Tue Oct 19, 2004 10:29 am Post subject: Re: simple for Schleife will nicht arbeiten |
|
|
Hi,
Axel Panning schrieb:
| Quote: | verstehe ich das richtig?
vector<anyclass>::iterator it=myvector.begin();
//fülle mit irgendwas
for ( it;it!=myvector.end();++it){
//irgendwas
}
Wenn ich das richtig verstehe, willst Du den begin-Iterator in 'it' |
speichern und danach myvector mit 'irgendwas' 'füllen'. Dieses Vorgehen
ist falsch, da der Iterator danach ungültig ist. Erst nach erfolgter
vector-'Befüllung' kannst Du Dir den Iterator holen.
| Quote: | ist schneller als
for ( it;it!=myvector.end();it++){
//irgendwas
}
wie handle ich dann das erste element ab?
it=myvector.begin()-1; dürfte wohl blödsinn ergeben oder?
Hier scheint ein fundamentales Mißverständnis über die Arbeitsweise der |
prä- und postinkrement-Operatoren vorzuliegen. Das Inkrementieren
passiert nicht etwa einmal am Anfang der Schleife und einmal am Ende
selbiger (so erscheint mir Deine Frage), sondern nur am Anfang bzw. am
Ende des (Teil-)Ausdrucks, in dem der Inkrement-Operator vorkommt.
MfG
Olaf Krzikalla
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Andreas Schmidt Guest
|
Posted: Tue Oct 19, 2004 2:09 pm Post subject: Re: simple for Schleife will nicht arbeiten |
|
|
| Quote: |
Grundsätzlich sollten einbuchstabige Variablennamen vermieden werden
(und im Grunde ist auch iJ ein solcher, das i ist ja nur bereits
erwähnter Präfix). i als Schleifenzähler ist üblich, wenn zu viele
verschachtelte Schleifen und damit j, k, ... nötig werden, ist das
oftmals ein Zeichen schlecht strukturierten Codes.
|
Nun, das mit den einbuchstabige Variablennamen ist eine Angewohnheit aus
VB. Das ich das i davor gesetzt habe, verdanke ich auch nur einem Buch :-)
| Quote: |
iB1 = (int) strlen(cS1) - 1;
iB2 = (int) strlen(cS2) - 1;
Dies sind C-Style-Casts. Besserer C++-Stil wäre (inkl. Deklaration, nach
Entfernen selbiger aus den vorangehenden Zeilen):
int iB1 = int(strlen(cS1)) - 1;
|
OK, setzte ich um ... Danke!!
| Quote: | iB1 und iB2 (B wie Länge? sind vom Typ unsigned int. Wenn z.B.
|
... B wie Länge kommt schon hin . Ich habe die Variablennamen
weitestgehend übernommen aus der VB Routine. Sollte Sie funktionieren,
werde ich wahrscheinlich eh mal alles ordentlich machen (JaJa ... ist
Doppelarbeit ... ich weiß)
| Quote: | strlen(cS1) 0 ist, ist iB1 unsigned(-1), also eine sehr hohe positive
Zahl. Da hilft auch der zwischenzeitliche Cast nichts.
Soll das letzte Zeichen wirklich ignoriert werden (- 1), oder ist das
ein Fehler beim Übersetzen von VB (dessen String-Behandlung ich nicht
kenne)?
|
Nun, das strlen brachte mir grundsätzlich eine Längenangabe die +1 der
originalen Anzahl an Buchstaben entspricht. Wenn ich das richtig verstanden
habe, liegt das an als Abschluss eines Strings im Speicher ... richtig??
Das ist ein Zeichen, was ich aber nicht auswerten will ... wobei es ja
evtl. auch keine große Rolle spielt.
Zeichenketten mit einer Länge Null werden der Routine nicht übergeben, das
checkt das Hauptscript vorher ab.
| Quote: | Wie bereits in den anderen Antworten gefunden: diese for-Schleife hat
einen leeren Anweisungsteil. Dies ist übrigens ein Nachteil der
Deklaration von iJ gleich am Anfang der Funktion. Mit diesem Konstrukt:
for (unsigned int iJ = 0; iJ < iB2 - iDist; ++iJ);
wäre der Fehler sofort aufgefallen, da dann im folgenden Block iJ nicht
mehr definiert wäre.
|
Ah ja ... OK, danke
| Quote: |
Schön' Gruß,
Malte
|
Vielen Dank!!
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Andreas Schmidt Guest
|
Posted: Tue Oct 19, 2004 2:12 pm Post subject: Re: simple for Schleife will nicht arbeiten |
|
|
| Quote: | In Anlehnung an ein Sprichwort: den Fisch hast Du ja nun schon bekommen.
Aber eigentlich fehlt Dir die Angel - mit einem Debugger hättest Du den
Fehler schnell selbst gefunden. Deswegen: besorge Dir einen Debugger
bzw. lerne den Umgang mit dem für Deinen Compiler mitgelieferten
Debugger. Variablenwerte läßt man sich während der Entwicklung nicht
durch irgendwohin geschriebene Ausgabestatements anzeigen, man schaut
sie sich im Debugger an.
|
Ja, Du hast Recht ... ist ne gaaanz schlechte Angewohnheit. Muss ich mir
abgewöhnen, wo das Programmierwergzeug doch sowas mitbringt.
| Quote: |
MfG
Olaf Krzikalla
|
Andreas
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Andreas Schmidt Guest
|
Posted: Tue Oct 19, 2004 2:12 pm Post subject: Re: simple for Schleife will nicht arbeiten |
|
|
SUPPER !!! :-)
Sorry für die späte Reaktion, aber hatte aber leider keine Zeit in die NG
zu schauen ... aber jetzt!!
Und daher:
Vielen Vielen Dank an alle!! Nicht nur das ich dadurch festgestellt habe,
das ich Blind bin (hab das Semikolon echt nicht gesehen, so oft ich die
Routine auch durchgeschaut habe), bin ich auch durch Eure Tipps gleich
schlauer. Werde mich mal mit std::string und Co beschäftigen.
Was die Definition der Variablen angeht, empfinde ich es an sich
übersichtlicher, alles am Anfang zu definieren, aber ich werd es mal
umsetzen und schauen, ob ich damit klar komme
Ansonsten schaue ich mir natürlich auch die vielen anderen Infos mal an.
Bye
Andreas
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Jörg Barfurth Guest
|
Posted: Wed Oct 20, 2004 9:01 am Post subject: Copy- oder Direct Initialization [Was: simple for Schleife w |
|
|
Hi Thomas,
Du - und manch anderer in dieser Gruppe - propagieren bei jeder sich
bietenden Gelegenheit die 'Funktionsstil-' (oder Direkt-)
Initialisierung. Das finde ich in dieser Allgemeinheit nicht
gerechtfertigt. Kopierinitialisierung ist ein vollwertiger Bestandteil
von C++. Anfängern, deren Kurs, Buch oder Arbeit oft abweichende
Vorgaben macht, solche Änderungen vorzuschlagen, auch wenn diese keinen
Unterschied machen, kann sogar Verwirung stiften.
Thomas Mang schrieb:
| Quote: | Außerdem kann man wieder die Funktionsstil-Initialisierung verwenden, was
bei komplexen iterator-Klassen und dummen Compilern eine weitere Kopie
spart:
|
Kennst du einen so dummen Compiler? Alle Compiler die ich kenne sparen
sich diese Kopie immer - i.d.R. sogar wenn Optimierungen ausgeschaltet
sind. Im Gegenteil findet man eher mal den Fehler, dass hier ein
fehlender Kopierkonstruktor unbemerkt bleibt.
Nach derselben Logik müsste man statt
void f( Something const & );
f( Something() );
besser
void f( Something const & );
{
Something arg;
f( arg );
}
schreiben, da im ersten Fall ein hirnverbrannter Compiler noch eine
Kopie anlegen darf.
Wenn man dies Argument also ignoriert, dann bin ich keineswegs
überzeugt, dass 'Funktionsstil'-Initialisierung grundsätzlich besser als
Kopierinitialisierung ist.
| Quote: | for (std::vector<anyclass>::iterator It(myvector.begin()),
End(myvector.end());
It != End; ++It)
{
// blah
}
|
Ein wesentlicher Vorteil der Kopierinitialisierung ist dass sie in
vielen Fällen zu besser lesbarem Code führt. Gerade das Beispiel einer
for-Schleife scheint mir da typisch.
Betrachten wir
for (Typ some(foo()),more(bar());some.test(more);baz(some),baz(more))
und
for (Typ some=foo(),more=bar();some.test(more);baz(some),baz(more))
Wenigstens für mich ist das zweite deutlich leichter lesbar.
Folgende Punkte tragen dazu bei, dass Kopierinitialisierung generell
lesbarer ist:
- Die visuelle Unterscheidung von Deklarationen und Funktionsaufrufen.
- Bei for-Schleifen: Vereinfachung des Klammerwaldes.
- Visuelle Ähnlichkeit zu Zuweisungen. [+]
- Analogie zu anderen, visuell ähnlichen Sprachen (Java, C)
[+] Natürlich ist es oft wichtig zwischen Zuweisungen und
Initialisierungen zu unterscheiden. Häufiger ist es aber m.E. so, dass
dieser Unterschied für das Verständnis des Programms auf höherer Ebene
(Algorithmus) unwesentlich ist.
Zur Lesbarkeit kommt noch hinzu, dass Kopierinitialisierung
- die Möglichkeit ungewollter impliziter Konvertierungen verringert.
(wenn auch nur geringfügig)
- nicht mit einer Funktionsdeklaration verwechselt werden kann.
Insgesamt reichen diese Vorteile für mich so weit, dass ich gelegentlich
sogar lieber
Typ t = Typ(...);
statt
Typ t(...);
verwende, wenn
Typ t = ...;
nicht möglich ist.
Ubrigens gibt es auch einen Fall, in dem nur die
Kopierinitialisierungssyntax möglich ist: Initialisierung in einer
/condition/. Also z.B.:
while (int selection=select_something()) ...;
if (T* t = dynamic_cast<T*>(p)) ...;
for (int index=0; X* x=getX(index); ++index) ...;
aber nicht
while (int selection(select_something())) ...;
if (T* t(dynamic_cast<T*>(p))) ...;
for (int index(0); X* obj(getX(index)); ++index) ...;
Gruss, Jörg
P.S.: Natürlich verwende ich auch oft Direktinitialisierung ...
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
Thomas Mang Guest
|
Posted: Wed Oct 20, 2004 8:53 pm Post subject: Re: Copy- oder Direct Initialization [Was: simple for Schlei |
|
|
"Jörg Barfurth" <jub.exp-aug04 (AT) gmx (DOT) net> schrieb im Newsbeitrag
news:cl59i8$r0r$1 (AT) news1 (DOT) ewetel.de...
| Quote: | Hi Thomas,
Du - und manch anderer in dieser Gruppe - propagieren bei jeder sich
bietenden Gelegenheit die 'Funktionsstil-' (oder Direkt-)
Initialisierung. Das finde ich in dieser Allgemeinheit nicht
gerechtfertigt. Kopierinitialisierung ist ein vollwertiger Bestandteil
von C++. Anfängern, deren Kurs, Buch oder Arbeit oft abweichende
Vorgaben macht, solche Änderungen vorzuschlagen, auch wenn diese keinen
Unterschied machen, kann sogar Verwirung stiften.
|
Natürlich kann es in gewissem Maße Verwirrung stiften. Das betrifft aber die
typ T = 1;
Initialisierung genauso. Mach mal eine Umfrage, wieviele sich da einen
Aufruf an operator= erwarten.
| Quote: |
Wenn man dies Argument also ignoriert, dann bin ich keineswegs
überzeugt, dass 'Funktionsstil'-Initialisierung grundsätzlich besser als
Kopierinitialisierung ist.
for (std::vector<anyclass>::iterator It(myvector.begin()),
End(myvector.end());
It != End; ++It)
{
// blah
}
Ein wesentlicher Vorteil der Kopierinitialisierung ist dass sie in
vielen Fällen zu besser lesbarem Code führt. Gerade das Beispiel einer
for-Schleife scheint mir da typisch.
Betrachten wir
for (Typ some(foo()),more(bar());some.test(more);baz(some),baz(more))
und
for (Typ some=foo(),more=bar();some.test(more);baz(some),baz(more))
Wenigstens für mich ist das zweite deutlich leichter lesbar.
|
Das liegt wohl sehr im Auge des Betrachters. Für mich ist beides gleich gut
lesbar - was natürlich nicht darauf schließen läßt, daß andere die eine oder
andere Art besser lesbarer finden.
| Quote: |
Folgende Punkte tragen dazu bei, dass Kopierinitialisierung generell
lesbarer ist:
- Die visuelle Unterscheidung von Deklarationen und Funktionsaufrufen.
- Bei for-Schleifen: Vereinfachung des Klammerwaldes.
- Visuelle Ähnlichkeit zu Zuweisungen. [+]
- Analogie zu anderen, visuell ähnlichen Sprachen (Java, C)
[+] Natürlich ist es oft wichtig zwischen Zuweisungen und
Initialisierungen zu unterscheiden. Häufiger ist es aber m.E. so, dass
dieser Unterschied für das Verständnis des Programms auf höherer Ebene
(Algorithmus) unwesentlich ist.
Zur Lesbarkeit kommt noch hinzu, dass Kopierinitialisierung
- die Möglichkeit ungewollter impliziter Konvertierungen verringert.
(wenn auch nur geringfügig)
- nicht mit einer Funktionsdeklaration verwechselt werden kann.
Insgesamt reichen diese Vorteile für mich so weit, dass ich gelegentlich
sogar lieber
Typ t = Typ(...);
statt
Typ t(...);
verwende, wenn
Typ t = ...;
nicht möglich ist.
|
Das setzt aber einen verfügbaren Kopierkonstruktor voraus.
| Quote: |
Ubrigens gibt es auch einen Fall, in dem nur die
Kopierinitialisierungssyntax möglich ist: Initialisierung in einer
/condition/. Also z.B.:
while (int selection=select_something()) ...;
if (T* t = dynamic_cast<T*>(p)) ...;
for (int index=0; X* x=getX(index); ++index) ...;
aber nicht
while (int selection(select_something())) ...;
if (T* t(dynamic_cast<T*>(p))) ...;
for (int index(0); X* obj(getX(index)); ++index) ...;
|
Das ist in der Tat ein Problem, und meiner Ansicht nach ein "bug" in der
Syntax.
Das gleiche betrifft auch arrays - die fressen auch nur die
Kopierinitialisierung.
Du darfst aber nicht vergessen, daß es semantische Unterschiede zw. den
beiden Initialisierungen gibt:
So muß etwa bei Kopierinitialisierung ein Kopierkonstruktor zugänglich sein
(ist z.B. nicht bei der iostream-Bibliothek gegeben).
Des weiteren schreibt man gerne:
typ T = 1;
statt
typ T = typ(1);
was wiederum eine Rolle spielt, falls der Konstruktor, der ein int (oder
einen Typ der von einem int umwandelbar ist) als Parameter erhält,
'explicit' ist. (Was zumindest bei mir praktisch alle
Ein-Argument-Konstruktoren sind).
Schließlich spielt die Anzahl an möglichen impliziten Umwandlungen eine
Rolle (Wir hatten hier unlängst ein Beispiel, wo die Kopierinitialisierung
nicht funktionierte, die Funktionsstilinitialisierung schon - einfach weil
die Kopierinitialisierung 2 implizite Umwandlungen gebraucht hätte).
Und zuletzt kannst Du in der Konstruktor-Initialisierungsliste nur die
Funktionsstilinitialisierung anwenden. Und die verwendest Du doch auch,
oder?
Aus Gründen der Symmetrie wegen scheint mir die Funktionsstil -
Initialisierung die vernünftigere zu sein.
Natürlich könnnten wir über den besser lesbaren Stil unendliche Diskussionen
führen, aber das würde wohl zu keinem Ziel führen.
Thomas
--
de.comp.lang.iso-c++ - Moderation: mailto:voyager+mod (AT) bud (DOT) prima.de
FAQ: http://www.voyager.prima.de/cpp/ mailto:voyager+send-faq (AT) bud (DOT) prima.de
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|