Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Problem mit Teilstring-Suchfunktion (reines C)

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
30.03.2007, 14:31 Uhr
Yadgar



High!

Zur Abwechslung frische ich mal meine lange verschütteten C-Kenntnisse auf (es soll ja auch heute noch Situationen geben, wo C statt C++ angesagt ist...) und programmiere mir ein kleines Progrämmchen, das META-Tags aus HTML-Seiten auslesen soll...

Ich dachte mir, ich fange dazu am besten mit einer Funktion an, die einen Teilstring in einem größeren String sucht und als Prototyp so aussieht:

short int strsrc(const char* str1, const char* str2)

strsrc gibt, falls str2 in str1 enthalten ist, den Indexwert des Beginns von str2 an der Stelle seines ersten Vorkommens zurück; falls str2 nicht vorkommt, soll -1 zurückgegeben werden.

Folglich sollte strsrc("Afghanistan grüßt den Rest der Welt!", "ist") den Wert 6 zurückgeben...

...tut es aber nicht, die Bedingung (!strcmp(sstring, str2)) wird niemals war, ich bekomme immer nur -1!

Hier der Code von strsrc:


C++:
#include <stdio.h>

#include <stdlib.h>



short strsrc(const char* str1, const char* str2)

{

  char* sstring;

  int a, b; /* Zähler für Gesamt- und Teilstring */

  short flag=0; /* zurückzugebende Beginn-Position des gefundenen Teilstrings */

  

  

  sstring = malloc(sizeof(str2)+1);

  if (!sstring)

  {

    printf("Speicher konnte nicht reserviert werden!\n");

    return -2;

  }

  for (a=0; a<strlen(str1)-strlen(str2)+1; a++)

  {

    for (b=0; b<strlen(str2); b++)

    {

      sstring[b]=str1[a+b];

    }

    /* sstring[b]=0; */

    printf("%s\n", sstring); /* Kontrollausgabe */

    if (strcmp(str1, sstring))

    {

      printf("%cbereinstimmung!",(char)154);

      return a;

    }  

  }

  

  return -1;

}




Am fehlenden Stringende-NULL kann es nicht liegen, auch wenn ich es nachträglich hinzufüge, bleibt das Programmverhalten gleich... und die Speicheranforderung ist auch in Ordnung! Was mache ich falsch?

Bis bald in www.khyberspace.de!

Yadgar
--
Flagmaker - ein Programmier-Blog

Dieser Post wurde am 30.03.2007 um 21:03 Uhr von Pablo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
30.03.2007, 14:49 Uhr
0xdeadbeef
Gott
(Operator)



C++:
int strsrc(char const *haystack, char const *needle) {
  char const *p = strstr(haystack, needle);

  return p != NULL ? p - haystack : -1;
}


?

Oder, lang

C++:
int strsrc(char const *haystack, char const *needle) {
  size_t n = strlen(needle);
  
  for(char const *p = haystack; *p; ++p) {
    if(memcmp(p, needle, n) == 0) {
      return p - haystack;
    }
  }

  return -1;
}


--
Einfachheit ist Voraussetzung für Zuverlässigkeit.
-- Edsger Wybe Dijkstra
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
30.03.2007, 15:48 Uhr
Yadgar



[quote 0xdeadbeef]
C++:
int strsrc(char const *haystack, char const *needle) {
  char const *p = strstr(haystack, needle);

  return p != NULL ? p - haystack : -1;
}



Das funktioniert einwandfrei... danke für den Tipp! Aber wieso funktionierte meine Version nicht?

Bis bald in www.khyberspace.de !

Yadgar
--
Flagmaker - ein Programmier-Blog
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
30.03.2007, 21:22 Uhr
Pablo
Supertux
(Operator)


Abgesehen davon, dass dein Agorithmus in O(n²) läuft (deine Implementierug sogar O(n^4)), ist deine Idee nicht schlecht, aber ... hier sind deine Fehler:

1.

C++:
sstring = malloc(sizeof(str2)+1);



es sollte sein


C++:
sstring = malloc(strlen(str2)+1);




sizeof liefert die Größe in Bytes, die str2 in Anspruch nimmt. Da str2 ein char* ist, bekommst du immer 4 (bei x68 Rechnern). Du willst aber die Länge der Zeichenkette, auf die str2 zeigt, also musst du strlen(3) nehmen.


2.


C++:
for (a=0; a<strlen(str1)-strlen(str2)+1; a++)



Gar nicht performant, denn bei jedem Schleifendruchlauf berechnest du die Länge von str1 und str2, also O(n). Es könnte aber deutlich schneller laufen, O(1), wenn du gemacht hättest


C++:
int len_str1, len_str2;
...
len_str1 = strlen(str1);
len_str2 = strlen(str2);
for (a=0; a<len_str1 - len_str2 +1; a++)



Du setzt auch im Voraus, dass len(str1) > len(str2) gilt. In deinem Fall passt, aber ist nicht allgemein gültig.

3.


C++:
for (b=0; b<strlen(str2); b++)




Siehe 2.

4.


C++:
/* sstring[b]=0; */
printf("%s\n", sstring); /* Kontrollausgabe */



Das war schon richtig, bis du es in /* ... */ gesteckt hast, sstring muss nul-terminiert sein, wenn du strcmp(3) nimmst. Außerdem hast du Glück, dass dein Programm nicht gleich beim printf abgeschmiert ist.

5.

C++:
if (strcmp(str1, sstring))



Erstens liefert strcmp eine 0 bei Übereinstimmung, etwas != 0 sonst.
Zweitens erwartet strcmp 2 nul-termnierende Zeichenketten, sstring ist es nicht.
Drittens strcmp vergleicht die Zeichenkette str1 mit sstring, ist logisch, dass strcmp nie 0 zurückliefert. Komisch, dass es nicht gleich beim ersten Schleifendruchlauf abbricht.

Was du hättest benutzen müssen: strncmp(3). strncmp vergleicht die ersten n Zeichen. Außerdem sollte es str2 heißen.


C++:
sstring[b]=0;
printf("%s\n", sstring); /* Kontrollausgabe */

if (!strncmp(str2, sstring, b))
{
    printf("Übereinstimmung\n");
    return a;
}




Zu Beefy's Lösung: strstr liefert einen Zeiger auf die Stelle, wo str2 in str1 vorkommt. Da der Speicher linear ist (damit meine ich, dass die Daten nicht fragmentiert sind), ist die Substraktion der Adresse der Überenstimmung und des Anfangs von str1 genau das Index, wo die Übereinstimmung stattfindet. Sprich, wenn str1 auf die Stelle n zeigt, und str2 stimmt auf Stelle n+k überein, dann liefert Beefy's funktion n + k - n = k.

6. Du machst nie


C++:
free(sstring);


--
A! Elbereth Gilthoniel!
silivren penna míriel
o menel aglar elenath,
Gilthoniel, A! Elbereth!

Dieser Post wurde am 30.03.2007 um 21:30 Uhr von Pablo editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: