Arrayfrage
-
Also auf const verzichten wo es nötig wäre ist ein enormer FEHLER da erstens der Benutzer der Schnittstelle wissen will ob seine Variablen verändert werden zweitens
der Programmierer selbst keinen Scheiß machen kann...
-
finix schrieb:
Was hast du gegen const?
'const' ist eine illusion
const int x = 10; int *p = (int*)&x; // huch? *p = 11; // undefined? printf ("%d %d\n", x, *p); // überraschung?
-
Ynnus schrieb:
Ich empfehle da kein unsigned integer sondern signed integer.
Auch nicht besser.
Ynnus schrieb:
Denn wenn er den Buchstaben nicht findet, was soll er zurückgeben?
Wie wärs mit 5? Oder anders formuliert, maximaler Index + 1. Auch gleichbedeutend mit strlen(array).
Es gibt mehr (und imo bessere) Alternativen als diesen unsinnigen -1 Dummy. Zudem passt bereits erwähnte Alternative zB besser zum nativen Algorithmus.size_t MyFind(const char* s, char c) { size_t pos = 0; while (s[pos] != '\0') { if (s[pos] == c) break; ++pos; } return pos; }
oder wer die Zeiger Variante bevorzugt
size_t MyFind(const char* s, char c) { const char* tmp = s; while (*s != '\0') { if (*s == c) break; ++s; } return tmp - s; }
net schrieb:
------------------ schrieb:
warning C4244: 'return' : conversion from '__w64 int' to 'int', possible loss of data
dann mach aus
return a-b-1;
das
return (int)(a-b-1);
oder schalt' den 64-bit modus aus
Oder wie wärs, wenn wir einfach mal die richtigen Datentypen verwenden, zB ptrdiff_t.
net schrieb:
------------------- schrieb:
Ynnus ist viel besser da der 1. parameter const ist!
das ist doch piepegal.
Nein, ist es nicht. Was ist, wenn jemand ein "Hallo" vom Typ 'const char*' hat? Eine Verwendung dieser mit der Funktion ist dann ohne Cast nicht möglich.
-
groovemaster schrieb:
Es gibt mehr (und imo bessere) Alternativen als diesen unsinnigen -1 Dummy.
ansichtssache. deine funktionen geben 0 zurück wenn nix gefunden wurde. das verschiebt das ergebnis nur um 1 nach vorne ;), aber weil das erste element eines arrays den index 0 hat, finde ich -1 als 'nicht gefunden' passender
groovemaster schrieb:
Oder wie wärs, wenn wir einfach mal die richtigen Datentypen verwenden, zB ptrdiff_t.
stimmt. das wär' die richtige antwort gewesen. gut dass wir dich haben
-
groovemaster schrieb:
Ynnus schrieb:
Ich empfehle da kein unsigned integer sondern signed integer.
Auch nicht besser.
Ynnus schrieb:
Denn wenn er den Buchstaben nicht findet, was soll er zurückgeben?
Wie wärs mit 5? Oder anders formuliert, maximaler Index + 1. Auch gleichbedeutend mit strlen(array).
Es gibt mehr (und imo bessere) Alternativen als diesen unsinnigen -1 Dummy.Ich wüsste jetzt nicht, wo es besser ist, eine 5 anstatt -1 auszugeben. (Die Unsinnigkeit musst du mir da erst erklären).
Dann muss man erstmal abfragen, ob das Array 5 Stellen hat. Ist dies nicht so, kann man erst dann schlussfolgern, dass das Zeichen nicht gefunden wurde. Außerdem ist dann der Rückgabewert bei "nicht gefunden" immer unterschiedlich, abhängig von der Arraylänge. Wo ist das bitte sinnvoller als eine -1. Da sieht man wenigstens direkt, dass der char nicht gefunden wurde.
Außerdem ist signed oder unsigned in dem Fall wohl praktisch gesehen wurscht, wer hat schon ein > 2 GB char-array? Da braucht man nicht noch das zusätzliche letzte Bit für noch größere Index-Werte.
Aber es muss tatsächlich nicht -1 sein. Beim späteren drüber Nachdenken ist mir in den Sinn gekommen, dass man auch 0 nehmen könnte. Denn an der Stelle 0 kann es auch nicht sein, in meiner Funktion beginnt das Zählen bei 1. (Also ist das gefundene Zeichen frühestens bei 1, also erstes Zeichen.) Dadurch könnte man auch die 0 als nicht gefunden interpretieren.
-
Deine Pointer-Methode gibt nicht korrekte Werte aus:
#include <iostream.h> char array[6] = "Hallo"; size_t MyFind(const char* s, char c) { const char* tmp = s; while (*s != '\0') { if (*s == c) break; ++s; } return tmp - s; } int main() { cout<<MyFind(array, 'a'); cin.get(); return 0; }
Dabei erhalte ich 2^32 als Ausgabe.
-
Ynnus schrieb:
@groovemaster:
Deine Pointer-Methode gibt nicht korrekte Werte aus:ersetz'
return tmp - s;
durch
return *s ? s - tmp : -1;
und statt 'size_t' als rückgabewert 'int'
-
net schrieb:
ansichtssache
Sicherlich, wie vieles.
net schrieb:
deine funktionen geben 0 zurück wenn nix gefunden wurde
Nein, tun sie nicht.
Ynnus schrieb:
Ich wüsste jetzt nicht, wo es besser ist, eine 5 anstatt -1 auszugeben.
Du gibst explizit -1 zurück, ich nicht. Damit machst du dich abhängig vom Rückgabetyp, bzw dessen Wertebereich.
Ynnus schrieb:
Dann muss man erstmal abfragen, ob das Array 5 Stellen hat.
Eigentlich nicht. Wenn du jedoch meinst, dass man die Länge des Strings kennen muss, dann hast du Recht. Und ich geb auch zu, dass
size_t pos = MyFind(array, 'a'); if (pos == strlen(array)) // nichts gefunden - bla
nicht sonderlich toll ist. Wir sind aber auch in C++, da nimmt man für Strings Container und kein strlen.
Ynnus schrieb:
Außerdem ist signed oder unsigned in dem Fall wohl praktisch gesehen wurscht
Praktisch vielleicht, logisch nicht. Wenn ich eine Funktion habe, die mir eine Position in einem Array sucht, warum sollte ich einen negativen Wert erwarten?
Ynnus schrieb:
Beim späteren drüber Nachdenken ist mir in den Sinn gekommen, dass man auch 0 nehmen könnte.
Nein, 0 ist unpraktisch. net hat zwar falsch interpretiert, aber zumindest teilweise richtig analysiert. Die Zählung beginnt bei 0, das ist also eine gültige Position. Wenn du wirklich bei 1 anfangen willst, ist das letztendlich auch nichts anderes als die -1 Variante. Du hast halt nur zum Rückgabewert 1 hinzuaddiert.
Ynnus schrieb:
Deine Pointer-Methode gibt nicht korrekte Werte aus
Sry, passiert halt. Die return Anweisung muss natürlich
return s - tmp;
lauten.
-
groovemaster schrieb:
Die return Anweisung muss natürlich
return s - tmp;
lauten.
und 'nicht gefunden' ist wie ein 'strlen()'
find ich doof
-
Praktisch vielleicht, logisch nicht. Wenn ich eine Funktion habe, die mir eine Position in einem Array sucht, warum sollte ich einen negativen Wert erwarten?
Wieso sollte ich 5 erwarten wenn es nur 4 gültige Stellen gibt? Da bleibt die Logik auch auf der Strecke. Ein fester Wert für "nichts gefunden" halte ich immer noch für sinnvoller.
Und irgendwo muss man seine Variable so wählen dass sie die negative 1 annehmen kann. Bei welchen Funktionen muss man nicht zusehen, dass die Rückgabewerte passend sind? Ich könnte jetzt bei deiner Funktion auch kein 2000-Zeichen-Array auf die letzte Ziffer prüfen und den Rückgabewert nur in eine byte Variable speichern wollen. Geht eben nicht, ebenso wie in meiner Funktion die Variablen signed sein müssen, und natürlich auch groß genug für die Werte.
Ich schätze das ist dann die persönliche Marke der Programmierer. Du bevorzugst eben deine Methode, ich die meine.Nein, 0 ist unpraktisch. net hat zwar falsch interpretiert, aber zumindest teilweise richtig analysiert. Die Zählung beginnt bei 0, das ist also eine gültige Position. Wenn du wirklich bei 1 anfangen willst, ist das letztendlich auch nichts anderes als die -1 Variante. Du hast halt nur zum Rückgabewert 1 hinzuaddiert.
Meine Zählung beginnt bei 1. Wieso ein Array bei 0 beginnt weiß ich nicht, aber wenn ich vor mir 10 Äpfel sehe, dann zähle ich nicht von 0 - 9 sondern von 1 - 10. Demnach geb ich als Rückgabe auch aus, dass das erste Zeichen sich an der ersten Stelle (also 1) und nicht bei 0 befindet. Immerhin ist es das ERSTE Zeichen und nicht das NULLTE Zeichen. Daraus resultiert, dass 0 als nicht gefunden durchaus interpretiert werden könnte. Wie oben reine persönliche Einstufung des Programmierers und ist demnach zu Handhaben wie man will. Man sollte es dann eben nur ordentlich dokumentieren für diejenigen die die Funktionen verwenden wollen. Und wenn man vorher sagt, dass die Funktion eine signed int verlangt und -1 als eindeutige Identifikation, dass nichts gefunden wurde, dann kann man das durchaus so nutzen.
-
net schrieb:
finix schrieb:
Was hast du gegen const?
'const' ist eine illusion
const int x = 10; int *p = (int*)&x; // huch? *p = 11; // undefined? printf ("%d %d\n", x, *p); // überraschung?
Würdest du auch
const int x = 10; int *p = const_cast<int*>(&x); // huch? *p = 11; // undefined? printf ("%d %d\n", x, *p); // überraschung?
schreiben?
-
finix schrieb:
Würdest du auch
const int x = 10; int *p = const_cast<int*>(&x); // huch? *p = 11; // undefined? printf ("%d %d\n", x, *p); // überraschung?
schreiben?
nee, ich mach das besser so:
#define NUR_DAS_IST_WIRKLICH_CONST 10 int *p = (int*)&NUR_DAS_IST_WIRKLICH_CONST; // error
da gibt's kein vertun, das kann man nicht weg casten
-
net schrieb:
da gibt's kein vertun, das kann man nicht weg casten
Troll nicht soviel rum
#define WERT 10 int main() { int const& r=WERT; int const* p=&r; int* evil = (int*) p; *evil=11; }
-
Shade Of Mine schrieb:
Troll nicht soviel rum
#define WERT 10 int main() { int const& r=WERT; int const* p=&r; int* evil = (int*) p; *evil=11; }
ich sehe nicht dass du WERT irgendwie verändert hast.
selber troll
-
net schrieb:
ich sehe nicht dass du WERT irgendwie verändert hast.
Was siehst du denn sonst?
Nachtrag:
aber da man Konstanten sowieso nicht verändern kann, ist diese Diskussion lächerlich. Tatscache ist, dass 10 nicht mehr konstant ist als int const i=10;
-
Shade Of Mine schrieb:
Tatscache ist, dass 10 nicht mehr konstant ist als int const i=10;
natürlich nicht
deshalb kannste ja in deinem beispiel die const-referenz indirekt verändern.
...aber das versuch mal mit WERT
const ist nun mal const, aber konstant ist was anderes
-
net schrieb:
deshalb kannste ja in deinem beispiel die const-referenz indirekt verändern.
...aber das versuch mal mit WERTWorauf willst du hinaus?
Der einzige Unterschied zwischen
#define DEFINE 10
und
int const CONST=10;ist der, dass man von DEFINE nicht die adresse nehmen kann, von CONST schon. Sonst gibt es aber keinen Unterschied.
Mit der nebensächlichen Ausnahme, dass DEFINE jedesmal ein 'anderer' Wert ist, der nur zufällig immer gleich ist und CONST immer das selbe. Ein Compiler macht aus beiden aber den selben Code (es sei denn, du nimmst die Adresse von CONST, dann könnte der Code uU etwas unterschiedlich aussehen).
-
Shade Of Mine schrieb:
Der einzige Unterschied zwischen
...dass man von DEFINE nicht die adresse nehmen kann, von CONST schon. Sonst gibt es aber keinen Unterschied.das ist ja der haken an der sache. alles was 'ne adresse hat kann man mit irgendwelchen bösen tricks zur laufzeit verändern (es sei denn, es befindet sich im ROM).
Shade Of Mine schrieb:
Ein Compiler macht aus beiden aber den selben Code (es sei denn, du nimmst die Adresse von CONST, dann könnte der Code uU etwas unterschiedlich aussehen).
das stimmt schon, aber da frag ich dich warum man von einer konstanten die adresse holen kann. es ist doch sinnlos und provoziert fehler. wieso erlaubt ein c++ compiler sowas?
-
net schrieb:
das ist ja der haken an der sache. alles was 'ne adresse hat kann man mit irgendwelchen bösen tricks zur laufzeit verändern (es sei denn, es befindet sich im ROM).
int const PI=3; int* p=(int*)&PI; *p=4;
schmiert bei mir ab.
const sollte nunmal in einem const-data Bereich liegen.
das stimmt schon, aber da frag ich dich warum man von einer konstanten die adresse holen kann. es ist doch sinnlos und provoziert fehler. wieso erlaubt ein c++ compiler sowas?
Ganz einfach: weil man eine Übergabe by reference ermöglichen muss. Eine konstante soll ja nicht magisch sein. Und wenn eine Funktion (aus welchen Gründen auch immer (zB wegen templates)) einen T const* erwartet, dann soll man ihr ein
int const pi=3;
foo(&pi);
geben können.Fände ich doof, wenn das nicht ginge.
-
net schrieb:
Shade Of Mine schrieb:
Der einzige Unterschied zwischen
...dass man von DEFINE nicht die adresse nehmen kann, von CONST schon. Sonst gibt es aber keinen Unterschied.das ist ja der haken an der sache. alles was 'ne adresse hat kann man mit irgendwelchen bösen tricks zur laufzeit verändern (es sei denn, es befindet sich im ROM).
Brauchst du dazu wirklich einen Kommentar?
net schrieb:
Shade Of Mine schrieb:
Ein Compiler macht aus beiden aber den selben Code (es sei denn, du nimmst die Adresse von CONST, dann könnte der Code uU etwas unterschiedlich aussehen).
das stimmt schon, aber da frag ich dich warum man von einer konstanten die adresse holen kann. es ist doch sinnlos und provoziert fehler. wieso erlaubt ein c++ compiler sowas?
Naja, wirklich sinnlos ist es wohl eher nicht, oder? Insbesondere wenn du nicht zwischen PODs und Objekten unterscheiden willst.
Und so direkt provoziert würde ich deinen const_cast nicht nennen; auch darüber hinaus fallen mir spontan keine Situationen ein wo const einen Fehler 'provozieren' könnte - eher andersrum.