C String Funktion strstr() selbst geschrieben

_mclaren_

Lieutenant
Registriert
Dez. 2006
Beiträge
909
Hallo!

Ich soll für C die strstr() Funktion selbst schreiben.
Sie funktioniert - zum Teil
Also mein Problem ist, wenn der String "suche" nicht im String "text" enthalten ist, bekommt ich ein Segmentation fault - ich weiß aber nicht wieso.

Und eine Frage, welchen Datentyp soll die Funktion idealerweise haben?

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int self_strstr(char *text, char *suche);

int main()
{

  char text[200]="Nun muss du suchen wo ich bin"; // hier soll dann gesucht werden
  //char suche[200]="xx"; // das soll gesucht werden - Segmentation fault!!
  char suche[200]="wo"; // das soll gesucht werden - funktioniert
  puts(self_strstr(text,suche));
}

int    self_strstr(char *text, char *suche){

      int i=0;
      int j=0;
      size_t suche_size;
      int position;

      suche_size = strlen(suche);

      while(text[i] != '\0' &&  suche_size != 0){ // bis Binäre Null im Text bzw. alle Feldelemente gefunden
        if(text[i]==suche[j]){
          suche_size--; 
          j++;
        }
        i++;
      }
      if (suche_size == 0){
        return &text[i-strlen(suche)];
      }
      else return NULL;
    }

danke vorab!
 
_mclaren_ schrieb:
Und eine Frage, welchen Datentyp soll die Funktion idealerweise haben?
Du meinst, was sie zurückgeben soll? Am besten das, was auch strstr zurückgibt. Der Compiler wirft bei mir auch jede Menge Warnungen. Die solltest du vielleicht erstmal abstellen.

Deine Funktion hat übrigens noch einen Fehler. Überleg dir mal, was bei
Code:
char text[200]="Wel 0123t";
char suche[200]="Welt";
passiert. Einen Segmentation fault kriege ich nicht.
 
Zuletzt bearbeitet:
neue Version - sollten nun keine Warnings mehr sein

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *self_strstr(char *text, char *suche);

int main()
{

  char text[200]="Nun muss du suchen wo ich bin";
  char suche[200]="Nun";
  puts(self_strstr(text,suche));
  //printf("Pointer: %s\n",self_strstr(text,suche));
  //printf("pointer: %d", &text[i-strlen(suche)]);
  return 0;
}


char  *self_strstr(char *text,char *suche){

      int i=0;
      int j=0;
      size_t suche_size;
      int position;

      suche_size = strlen(suche);

      while(text[i] != '\0' &&  suche_size != 0){ /
        if(text[i]==suche[j]){ 
          suche_size--;
          j++; 
        }
        i++; 
      }
      if (suche_size == 0){
        return &text[i-strlen(suche)];
      }
      else return NULL;
    }

Danke für den Hinweis, weiß schon was du meinst ... muss mal überlegen wie ich das unterbinden kann
 
hi,
hier mal ne ähnliche Funktion als Beispiel:

Code:
// Rüchgabe: -1 oder Index
int InStrA(int iStartPos,char* Str1,char* Str2)
{

    int szSize,iStr2,iTmp;

    for(szSize=0;Str1[szSize] != 0;szSize++){}; //StrSizeA
    if(iStartPos>=szSize)   // Index auserhalb Str1
        return(-1);         // -1 -> nicht gefunden bzw Fehler

    if( Str2[0] == 0 )      // leerer string?
        return(-1);

    for(int iStr1=iStartPos;Str1[iStr1] != 0; iStr1++)
    {
        if(Str1[iStr1] == Str2[0])
        {
            for(iStr2=0,iTmp=iStr1;(Str1[iTmp]!=0)&&(Str2[iStr2]!= 0)&&(Str1[iTmp]==Str2[iStr2]);iStr2++,iTmp++){}; // Schleife bis zur ersten Unstimmigkeit
            if(Str2[iStr2]== 0)     // Str2 komplet in Str1 gefunden?
                return(iStr1);      // gefunden! -> index zürückgeben

        }
    }
    return(-1);     // -1 -> nicht gefunden
}
 
ich hab das nun behoben denk ich - aber --> Seg fault

@Darii Seg fault kam, wenn der such String überhaupt nicht im text String war.

@Woey danke - da wird mit ner for gesucht bis eine übereinstimmung, dann die anderen . das sind so viele verschachtelungen, das wollt ich unterbinden ...
 
Zuletzt bearbeitet:
_mclaren_ schrieb:
@Darii Seg fault kam, wenn der such String überhaupt nicht im text String war.
Wie gesagt, bekomme ich nicht.

Danke für den Hinweis, weiß schon was du meinst ... muss mal überlegen wie ich das unterbinden kann

Code:
if(text[i]==suche[j]){ 
          suche_size--;
          j++; 
        } else {suche_size= strlen(suche) ; j = 0}

Sollte reichen.
 
Zuletzt bearbeitet:
ich meine, wenn es absolut keine Übereinstimmung gibt *g*
dann auch nicht?

Dein Wel 0123t ... Wel hat bei mir auch funktioniert (vor der Abänderung).

Was spuckt die letzte Version bei dir aus?

edit: wir überschneiden uns da immer *g*
stimmt sollte reichen, si einfacher und übersichtlicher .. danke
 
Zuletzt bearbeitet:
_mclaren_ schrieb:
ich meine, wenn es absolut keine Übereinstimmung gibt *g*
dann auch nicht?
und ich bekomme da absolut keinen segfault(gcc4.0 falls es hilft). Tendenziell würde ich drauf tippen, dass sich puts und der Nullpointer nicht vertragen.

Was spuckt die letzte Version bei dir aus?
Gar nichts, immer (null)
 
interessant.

Also im Codeblocks meine Programmier umgebung --> Seg fault
und direkt in der Linux Konsole ebenso *grübl*

@Darii
EDIT: du hattest recht - puts und nullpointer Vertragen sich scheinbar nicht - hab nun printf

Danke, Danke, Danke ;)

hier up to date

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *self_strstr(char *text, char *suche);

int main()
{

  char text[200]="Wel 0123t";
  char suche[200]="Welt";
  printf("%s",self_strstr(text,suche));
  return 0;
}


char  *self_strstr(char *text,char *suche){

      int i=0;
      int j=0;
      size_t suche_size;
      int trefferposition = 0;

      suche_size = strlen(suche);

      while(text[i] != '\0' &&  suche_size != 0){ // solange durchlaufen bis Binäre Null im Text erreicht wurde bzw. solange bis alle Feldelemente von String suche gefunden wurden
        if(text[i]==suche[j]){ // Wenn Feldelemente von text und suche übereinstimmen
          trefferposition = i;
          suche_size--;
          j++;
        } else {
            suche_size = strlen(suche);
            j = 0;
          }
        i++;
      }
      if (suche_size == 0){
        return &text[i-strlen(suche)];
      }
      else return NULL;
    }
 
Zuletzt bearbeitet:
Als Ergänzung:


&text[i-strlen(suche)] = text+i-strlen(suche)

Zeigerarithmetik ftw


Man hätte im Übrigen auch daran denken sollen, dass man keiner Funktion, die char* erwartet (puts), ungeprüft einen int-Wert übergibt, der noch dazu nur ein Offset (relativ) ist, und keine absolute Adresse.

In C findet dabei ein implicit cast statt, der den int-Wert zu einem Zeiger macht und ich wage stark zu bezweifeln, dass Du im Protected Mode Zugriff auf den unteren Speicherbereich besitzt.


Du solltest jetzt auch nicht dazu übergehen, anderen Funktionen (hier printf) die Fehlerbehandlungen übernehmen zu lassen...
 
Hallo!

Danke
Zeigerarithmetik, stimmt, danke, aber den zweiten Teil begreif ich nicht ganz.
Wie, was sollt ich sonst machen für die Ausgabe?
 
hi,

wollt nur mal kurz anmerken das die generelle Logik deiner Funktion fehlerhaft ist. Hierzu mal ein Beispiel bei dem deine Funktion 0 zurückgibt obwohl der String vorhanden ist:
self_strstr("abababc","ababc")


grüße, Woey
 
Zuletzt bearbeitet:
Ich würds so in der Art implementieren:
Code:
int i,j found, end = strlen(text) - strlen(suche);

for(i = 0; i < end; ++i){
 if(text[i] == suche[0]){   // erstes Zeichen stimmt überein => genauer untersuchen
   found = 1;    // 1 bedeutet: alles ok
   for(j = 1; j < strlen(suche); ++j){
    if(text[i+j] != suche[j]){       // eine Stelle stimmt nicht überein => abbrechen
      found = 0;
      break;
    }
   }
   if(found == 1) return text+i;       // alles war ok, pointer zurückgeben
 }
}
return null;       // nichts gefunden
 
Zuletzt bearbeitet:
Woey schrieb:
hi,

wollt nur mal kurz anmerken das die generelle Logik deiner Funktion fehlerhaft ist. Hierzu mal ein Beispiel bei dem deine Funktion 0 zurückgibt obwohl der String vorhanden ist:
self_strstr("abababc","ababc")


grüße, Woey

stimmt - das hab ich wahrlich übersehen! :/

DANKE für den Hinweis!

Habs nun korrigiert . gibts noch etwas das nicht beachtet wird?

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *self_strstr(char *text, char *suche);

int main()
{

  char text[200]="abababcdfdgf";
  char suche[200]="ababc";
  printf("%s\n",self_strstr(text,suche));
  return 0;
}


char  *self_strstr(char *text,char *suche){

      int i=0;
      int j=0;
      size_t suche_size;

      suche_size = strlen(suche);

      while(text[i] != '\0' &&  suche_size != 0){
        if(text[i]==suche[j]){
          suche_size--;
          j++;
        } else {
            suche_size = strlen(suche);
            j = 0;
[B][COLOR="Red"]            i=i-j;[/COLOR][/B] // hüpfe zum zu letzt Verglichenen Feld von String text
          }
        i++;
      }
      if (suche_size == 0){
        return text+i-strlen(suche);
      }
      else return NULL;
    }
 
Zuletzt bearbeitet:
Hallo! Danke, aber nachdem ich Anfänger bin mach ichs lieber selbst, das ist mehr Lerneffekt dahinter *g* ;)
Außerdem tu ich mir teilweise schwer die Logik von fremden Programmen nach zu vollziehen, da ich schneller bin wenn ich es selbst programmier ...
 
Wenn man fremden Code liest und versteht, hat das aber durchaus auch einige Lerneffekte ;) Aber gut, hast schon recht. Will dich ned vom Programmieren abbringen.
 
hier mal mein Vorschlag:

Code:
char  *self_strstr(char *text,char *suche){

      int i=0;
      int j=0;
	  int save=0;
	  bool cmp=false;
	
      while(text[i] != 0)
      {
  			if(text[i] == suche[j] && suche[j] != 0)
  			{
  				if(cmp == false)
  				{
  					cmp = true;
  					save=i;
  				}
  				j++;
  			}
  			else
  			{
  				if(cmp == true)
  				{
  					if(suche[j] == 0)
  					{
  						return(save+text);
  					}
  					cmp =false;
   					i = save;
   					j = 0;
   				}
   				else
   				{
   					if(suche[j]==0)return(0);// leerer string
   				}
  			}
  			i++;
      }
	
		return((suche[j]==0 && cmp == true)?(save+text):(0));
    }

EDIT: wie kommst du auf i=i-2 -> das wird wohl kaum funktionieren
EDIT2: wahr noch ein kleiner Fehler im code - behoben
 
Zuletzt bearbeitet:
man muss den index "i" auf die Ausgangsposition zurück setzen - das ist die Position an dem der Vergleich mit "suche" begonnen hat.
 
Zuletzt bearbeitet:
Zurück
Oben