Problem mit pointern



  • Hallo Leute,

    ich bin noch recht frisch im bereich c++ und muss mich mit pointern auseinander setzten

    ich würde euch gerne mal die aufgabe zeigen die ich am bearbeiten bin und hoffe das ihr mir sagen könnt, wo evtl der fehler liegt, weil ich finde ihn einfach nicht.

    #include <iostream>
    #include "suche.cpp"
    
    using namespace std;
    
    const int LAENGE=200;
    
    int main(){
    	//variablen deklaration
            char* kette = new char[LAENGE];
    
            cout << "Bitte Zeichenkette angeben :" <<endl;
            cin >> kette;
            cout << "Bitte das zu suchende Zeichen angeben: ";
            cin >> zeichen;        	 
    
      	 tmp = searchChar(kette,zeichen);
          	 cout << tmp;
    

    das ist meine main
    bevor nun kommt warum ich das nicht mit string mache ... darf ich nicht und das hier dient auch zur übung wegen verständnis von pointern, was eigentlich nicht so schwer ist, aber irgendwie gelingt mir nicht die übergabe zu meiner funktion die so ausschaut

    int searchChar(char* kette, char zeichen){
            char* posi = kette;
            int tmp = -1;
            int zaehler=0;
    
            while(posi++){
            	if (*posi==zeichen){
            		return zaehler;
            	}
            	zaehler++;
            }
    }
    

    hoffe irgendwer könnte mir sagen wo ich einen denk fehler drin habe

    mfg
    foexle



  • Was geht denn genau nicht?

    Spontan sehe ich, dass der mit new allozierte Speicher nicht mit delete freigegeben wird (erzeugt ein Memory Leak).

    int tmp wird nicht gebraucht, also raus damit.

    Das umkopieren des Pointers nach posi ist nicht nötig, da der Pointer schon by Value übergeben wird.

    Ausserdem ist zeichen nicht definiert... ev. ist das nur hier im Forums Code so.

    Grüsse
    Simon



  • SUCHE BENUTZEN, wurde TAUSEND MAL besprochen!



  • gugugs 🙂

    danke für die schnelle antwort ..

    ja zeichen ist definiert, vergessen hier rein zu kopieren ... das mit dem speicherleek hast du recht, aber das ist ja noch nicht das gesamte programm 🙂 der wird nacher freigegeben.

    evtl liegt es auch daran, das ich das vöoolig falsch übersetzte.

    <xxx>g++ suche.cpp ueb03.cpp
    /tmp/cc6OqWdK.o: In function searchChar(char*, char)': ueb03.cpp:(.text+0x0): multiple definition ofsearchChar(char*, char)'
    /tmp/cc0RFz2x.o:suche.cpp:(.text+0x0): first defined here
    collect2: ld gab 1 als Ende-Status zurück

    in der suche ist die function drin ....

    und ja ich weis wie man in einem forum vorgeht 😛 sicher habe ich die suche benutzt, aber da ich noch sehr wenig erfahrung habe, kann ich die keine passende antwort auf meine frage finden



  • #include "suche.cpp"
    

    Man inkludiert die Header und nicht die Implentierungs-Dateien. (Nennt man die so?)



  • hi,
    in der geposteten funktion int searchChar(char* kette, char zeichen)
    ist das hier while(posi++) recht ungünstig, weil nämlich
    hier if (*posi==zeichen)
    der inhalt von *posi das zweite zeichen von kette ist ( falls strlen(kette) >= 2 )
    d.h. wenn jemand ein "a" als zeichenkette eingibt, wirst du es nie finden 😉



  • du inkludierst die suche.cpp in deiner ueb03.cpp datei, damit machst du suche.cpp und ueb03.cpp zu einer einzigen übersetzungseinheit. dann sagst du dem compiler, dass suche.cpp außerdem noch eine eigene übersetzungseinheit darstellt. zweimal dieselbe definition in zwei verschiedenen übersetzungseinheiten ist aber ein fehler.
    lösung: entweder in ueb03.cpp suche.cpp nicht inkludieren und die funktion searchChar nur deklarieren (in den FAQs gibt es einen beitrag, der dir den unterschied zwischen definition und deklaration erklärt), das ist der weg, den du gehen solltest.
    oder: du sagst g++, er soll nur eine übersetzungseinheit (ueb03.cpp) übersetzen.

    zum inhalt der funktion:

    int searchChar(char* kette, char zeichen){
            char* posi = kette;
            int tmp = -1;
            int zaehler=0;
    
            while(posi++){
                if (*posi==zeichen){
                    return zaehler;
                }
                zaehler++;
            }
    }
    

    das erste was du machst, ist posi zu inkrementieren. das heißt nun, das du erst bei index 1 (und nicht 0) anfängst. danach die schleifenbedingung: du durchsuchst den string solange, bis du das passende zeichen findest, nur leider ist die abbruchbedingung vermurkst: posi wird solange inkrementiert, bis es über den maximalwert hinausgeht und wieder bei 0 ankommt. d.h. wenn deine funktion nach einem zeichen suchen soll, das nicht in deinem char* enthalten ist, wird es wahrscheinlich eine access violation geben. im schlimmsten fall wirst du von kleinen, roten gnomen attackiert.

    abgesehen von diesen logischen fehlern solltest du die zeichenkette als const char* übergeben, du änderst sie ja nicht. außerdem solltest du bei g++ mal die option -Wall aktivieren. dann sagt dir g++ auch, dass es die möglichkeit gibt, dass deine funktion, die eigentlich einen int zurückgibt, beendet und gar nichts zurückgibt.

    auf jedenfall gibt es mehrere lösungen für dich.
    straight-forward, einfach die fehler, die ich aufgezählt habe ausmerzen:
    mit kette bei index 0 anfangen, am ende der schleife inkrementieren, falls das nächste zeichen eine '\0' ist, abbrechen. sieht so aus:

    do //mit index 0 anfangen
    {
      if (*posi==zeichen){ 
       return zaehler;
      }
      ++zaehler;
    } while (*++posi); //inkrementieren und überprüfen in einem
    return -1; //not-found
    

    oder du subtrahierst zwei zeiger voneinander, dann bekommst du ebenfalls den richtigen wert:

    do
    {
      if (*posi==zeichen) return posi - kette;
    } while (*++posi);
    return -1; //not-found
    

    dann sollte dein rückgabetyp allerdings nicht int (auch wenn das möglich ist), sondern ptrdiff_t (aus <cstddef>) sein.



  • ok danke für die ausführliche erklärung

    das hilft schon sehr weiter 😃 zumindest mal das mit dem include verstanden und auch wegen compelieren 🙂

    das andere versuch ich sofort 🙂

    danke



  • foexle schrieb:

    ...
    bevor nun kommt warum ich das nicht mit string mache ... darf ich nicht und das hier dient auch zur übung wegen verständnis von pointern, ...

    Dann sag Deinem Lehrer mal, dass er nicht "Zeiger-Übungen" mit "Zeichenketten-Übungen" mischen soll. Das führt zu einem "Zweifrontenkrieg" (Rumschlagen mit 0-Terminierung, str-/printf-/IO-Funktionen, SegFaults, ...) und schlechten Gewohnheiten.
    Wenn er kein Beispiel mit einem int-Array zustande bekommt, sollte er sein Gehalt zurückgeben.

    😃

    Gruß,

    Simon2.


Anmelden zum Antworten