Arrayfrage



  • @groovemaster:

    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 WERT 😃

    Worauf 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.



  • net schrieb:

    const int x = 10;
    int *p = (int*)&x; // huch?
    *p = 11; // undefined?
    printf ("%d %d\n", x, *p); // überraschung?
    

    Ne keine Überraschung x bleibt 10 und jetzt?!?



  • net schrieb:

    und 'nicht gefunden' ist wie ein 'strlen()'

    Nein, nicht wie strlen. strlen gibt nur zufälligerweise den gleichen Wert zurück.

    Ynnus schrieb:

    Wieso sollte ich 5 erwarten wenn es nur 4 gültige Stellen gibt?

    5 ist eine logische Fortsetzung der Positionszählung, -1 nicht.

    Ynnus schrieb:

    Ein fester Wert für "nichts gefunden" halte ich immer noch für sinnvoller.

    Kann letztendlich jeder machen wie er lustig ist. Ich halte solche einzelnen Dummy Werte in vielen Situationen für Blödsinn.

    Ynnus schrieb:

    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?

    Eben, du passt deinen Rückgabetyp dem "Fehlerwert" an, ich nicht. Ich nehm einfach den passenden Typ für die benötigte Funktionalität.

    Stell dir einfach mal eine nativere Heransgehenweise vor. Du hast ein Array und suchst nach einem Wert. Welche Parameter brauchst du? Genau, das Array selbst, die Länge und den zu suchenden Wert.

    size_t suche(int* feld, size_t len, int wert)
    

    Jetzt lässt du suchen, und erhälst als Rückgabe einen Wert dir irgendwas zwischen 0 und len-1 ist. Wurde nichts gefunden, erhälst du len. Ist für mich jedenfalls logischer als irgendwie einen unpassenden Fehlerwert herbeizuzaubern.

    Ynnus schrieb:

    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.

    Dann hast du aber definitiv den falschen Rückgabetyp gewählt, denn der letzte mögliche Index (1999) passt dann auch nicht rein.

    Ynnus schrieb:

    Geht eben nicht, ebenso wie in meiner Funktion die Variablen signed sein müssen, und natürlich auch groß genug für die Werte.

    Schon klar. Nur sollte man sich darüber im Klaren sein, dass man sich mit einem signed Typ gleich die Hälfte des möglichen Wertebereichs nimmt. Ob man den wirklich braucht, ist dabei 'ne andere Frage.

    Ynnus schrieb:

    Meine Zählung beginnt bei 1. Wieso ein Array bei 0 beginnt weiß ich nicht

    Weil man in C++ nunmal nicht "zählt", sondern die Indizes als Offset betrachtet. Und bis zum 1. Element ist nunmal nix. Ich würde dir deshalb empfehlen, auch mit 0 für den 1. Index zu arbeiten. Das ist in C++ gebräuchlich, nicht nur bei Arrays. Ansonsten bist du in VB vielleicht besser aufgehoben. 🙂



  • Hi,

    Will auch mal wertend meinen Senf dazugeben:

    zum Thema "const"-Qualifizierer:
    Ich find es absolut unsinnig diesen zu vermeiden und nicht zu benutzen. Um Fehler zu vermeiden und Lesern des Codes das lesen zu vereinfachen.
    Desweiteren werden const Variablen teilweise in schreibgeseschützten Datenbereichen gespeichert, so wie man es sich auch wünscht.

    zum Thema Rückgabewert der "Such-Funktion", falls der Suchterm nicht vorhanden ist:
    Es gibt ja an sich die 2 Varianten, die eine bei der der Pointer auf die Fundstelle zurückgegeben wird, so machen es die C-Standardfunktionen und die die Position der Fundstelle im String zurückgibt.
    Die Rückgabe von NULL bzw. -1 finde ich persönlich sinnvoll, da die Abfrage, simpler ist. Und die NULL ist sowieso keine gültige Position, das schränkt den Wertebereich also an sich nicht ein und wenn man meint, man müsse bei der zweiten Variante Möglichkeiten haben mit mehr als 2 GB Strings zu arbeiten, dann kann man ja unsigned int zurückgeben und falls nicht gefunden wird, -1 nach unsigned int casten, bzw. gleich 0xFFFFFFFF zurückgeben.

    MfG
    DDR-RAM



  • finix schrieb:

    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.

    haste ja gesehen, mein code mit dem pointer und der von shady mit der referenz. zugegeben, das sind willkürliche beispiele mit absichtlichem wegcasten von 'const'. aber immerhin, ich find's bedenklich was man mit 'const' für'n quatsch machen kann 😃

    dali schrieb:

    net schrieb:

    const int x = 10;
    int *p = (int*)&x; // huch?
    *p = 11; // undefined?
    printf ("%d %d\n", x, *p); // überraschung?
    

    Ne keine Überraschung x bleibt 10 und jetzt?!?

    dein compiler macht das so. und was macht ein anderer? und was ist mit der 11? wo wird die gespeichert?

    DDR-RAM schrieb:

    Hi,
    Desweiteren werden const Variablen teilweise in schreibgeseschützten Datenbereichen gespeichert, so wie man es sich auch wünscht.

    nicht immer. ich kenne zum beispiel einen c-compiler der speichert const-sachen trotzdem im ram. der meckert dann zwar, wenn man im code schreibend drauf zugreifen will, aber mit nem 'int* p =(int*)adresse' kannste das trotzdem umgehen. wenn man den dazu bewegen will, was in's rom zu tun, geht das nur mit 'nem #pragma.

    btw: schreibt der c++ oder c-standard eigentlich vor, dass const-objekte physikalisch read-only gespeichert werden müssen?



  • net schrieb:

    DDR-RAM schrieb:

    Hi,
    Desweiteren werden const Variablen teilweise in schreibgeseschützten Datenbereichen gespeichert, so wie man es sich auch wünscht.

    nicht immer. ich kenne zum beispiel einen c-compiler der speichert const-sachen trotzdem im ram. der meckert dann zwar, wenn man im code schreibend drauf zugreifen will, aber mit nem 'int* p =(int*)adresse' kannste das trotzdem umgehen. wenn man den dazu bewegen will, was in's rom zu tun, geht das nur mit 'nem #pragma.

    😉
    Also, ich habs getestet mitm VC++ 2003 und ne globale constante Variable, die ich derefenziert habe, war in einem schreibgeschützten Speicherbereich und eine lokale befand sich auf dem Stack, also nicht schreibgeschützt.
    Konstante Arrays wird er wahrscheinlich auch nem schreibgeschützten Speicherbereich aufheben, egal ob global oder lokal, aber ích hab es nicht getestet, da ich normalerweise davon ausgehe, das const = const ist und const bei mir nicht weggecastet wird 🙂

    btw: schreibt der c++ oder c-standard eigentlich vor, dass const-objekte physikalisch read-only gespeichert werden müssen?

    Weiß ich nicht. 😃

    MfG
    DDR-RAM


Anmelden zum Antworten