Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Substring

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 < [ 2 ]
000
02.04.2003, 03:42 Uhr
Adi Suter



Hallo zusammen,

ich habe einen String, zum Beispiel


C++:
char *s = "Hello World!";


Nun möchte ich einen substring davon nehmen, und zwar unter Angabe von Positions-Werten. Also zum Beispiel: "Gib mir den Substring von Position 4 bis und mit Position 10 aus". Was dann zu folgender Ausgabe führen würde

lo Worl

Gibt es die Möglichkeit eine Funktion zu schreiben, welche mir das ganze erfüllen würde. Zum Beispiel eine Funktion substr in folgender Art:


C++:
char *r = "";
substr(*r, *s, 4, 10);


Liebe Grüsse
Adi Suter

Dieser Post wurde am 02.04.2003 um 03:45 Uhr von Adi Suter editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
02.04.2003, 07:43 Uhr
virtual
Sexiest Bit alive
(Operator)


Ja, die Möglichkeit gibt es. Aber wo ist Dein Ansatz?
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
02.04.2003, 10:59 Uhr
Adi Suter



Hallo virtual,

vielen Dank für deine Antwort. Was für einen Ansatz? Ich habe leider überhaupt keine Ahnung, wie ich das lösen könnte. Vielleicht folgendermassen


C++:
char* substr(char *source, int begin, int end) {
  char *r = "" // init return //

   ???

   return r;
}


Ich habe keine Idee, wie ich den string source kürzen kann. Kannst du mir da nicht weiterhelfen? Vielleicht weisst du ja sogar einen gute Seite, wo ich diese Funktion finden könnte.

Liebe Grüsse
Adi
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
02.04.2003, 11:41 Uhr
~dirweis
Gast


/*servus adi,
ich versuchs mal...*/

char *substr(char *source, int begin, int end) /*ganz wichtig!! der stern muss nach dem leerzeichen stehen (der für die funktion), sonst gibst du keinen string zurück!!*/
{
char *r=source;
int zlr, flag=0;

for(zlr=0;zlr<strlen(source);zlr++)
{
if(begin==zlr) flag=1;
if(flag)
{
*r=zlr;
r++;
}
if(end==zlr) break;
}
return *r;
}

/*kann dir leider nicht mehr erklären, was ich da mache, keine zeit mehr. wenn du es wissen willst, sag bescheid

gruss dirk*/
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
02.04.2003, 12:00 Uhr
Adi Suter



Seins griesst,

vielen Dank für den Versuch. Aber ich erhalte leider eine Fehlermeldung:

warning C4047: 'return' : 'char *' differs in levels of indirection from 'char ' und zwar auf die Zeile
C++:
return *r;

Als ich den Stern weglies, da konnte ich alles erfolgreich kompilieren, aber als es dann an die Stele kommen sollte, bekam ich einen Programmfehler Die Anweisung in "0x00401259" verweist auf Speicher in "0x004200da". Der Vorgang "written" konnte nicht auf dem Speicher durchgeführt werden. und zwar auf der Zeile
C++:
*r = zlr;


Vermutlich stimmen da die Poiner-Adressen nicht. Ich werde da mal noch weiter versuchen.

Liebe Grüsse
Adi
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
02.04.2003, 12:04 Uhr
virtual
Sexiest Bit alive
(Operator)



Zitat:
~dirweis postete

...
char *substr(char *source, int begin, int end) /*ganz wichtig!! der stern muss nach dem leerzeichen stehen (der für die funktion), sonst gibst du keinen string zurück!!*/
...


Na, also da musst Du mir schon mal näher erklaren. Ist mein erstes Hören!

Wenn Der Eingabestring durch die Routine verändert werden darf, wäre die einfachste Lösung wohl:

C++:
char* substr(char* source, int begin, int end)
{
   source[end+1] = 0;
   return source+begin:
}



Die routine hat in ihrer Kürze zwei Nachteile:
1. source wird verändert. Wenn Du das nicht willst, musst Du dir überlegen, wohin du den Substring schreiben willst. Da hast Du prinzipiell drei Möglichkeiten: (a) Zeiger auf den Speicher, wo das Resultat hin soll, mit an die Funktion übergeben, (b) Speicher in der Funktion für das Resultat belegen, oder (c) Resultat in einer static variablen speichern und diese zurückgeben. Alle Lösungen haben Vor und nachteile. (Will ich mal einen FAQ Artikel zu machen).
2. Es wird kein Errorcheck gemacht.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
02.04.2003, 12:15 Uhr
Adi Suter



Ich erhalte immer die Meldung einer Speicherverletzung. Woher kommt denn das?


C++:
#include <stdio.h>
#include <string.h>

char* substr(char* source, int begin, int end)
{
  source[end+1] = 0;
  return source+begin:
}

main (int argc, char *argv[])
{
  printf ("%s", substr("HELLO WORLD", 2, 4));
}


Liebe Grüsse
Adi
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
02.04.2003, 12:36 Uhr
Adi Suter



Okay Leute,

ich habe eine Möglichkeit gefunden. Man kann vermutlich die einzelnen Chars eines char-pointers nicht ändern.


C++:
char *substr(char* source, int begin, int end)
{
    char r[255];
    int len = strlen(source);
    int zlr = 0, j = 0;

    for ( zlr=begin; zlr <= end; zlr++ )
    {
        r[j] = source[zlr];
        j++;
    }
    r[j] = '\0';

    return r;
}



Das Problem, Der String darf maximal 255 Zeichen beinhalten! Oder was man auch immer angibt.

Und wenn die Funktion ein zweites Mal aufgerufen wird, dann wird komischerweise das Resultat des ersten Aufrufes auch abgeändert.

Dieser Post wurde am 02.04.2003 um 12:51 Uhr von Adi Suter editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
02.04.2003, 13:09 Uhr
virtual
Sexiest Bit alive
(Operator)


Die Speicherverletzung kommt daher, daß "HELLO WORLD" ein konstanter String ist, der nicht verändert werden darf. Dein Program sollte so nicht abstürzen:

C++:
int main (int argc, char *argv[])
{
char buffer[255];
strcpy(buffer, "HELLO WORLD");
printf ("%s", substr(buffer, 2, 4));
}


Deine Lösung im Letzten Post funktioniert nur zufällig: r ist eine lokale Variable; sobald du die Routine verläßt, kann der Inhalt von r (und damit der sub-String) anderweitig genutzt worden sein oder gar nicht mehr existieren.
Ich habe da mal die drei eben erwähnten Lösungsmöglichkeiten kurz aufgeschrieben:

C++:
#include <stdio.h>
#include <stdlib.h>

/* Lösungsansatz 1: Der substring wird in dynamischen Speicher
   Angelegt.
   Vorteil: beliebige Stringlängen möglich
   Nachteil: Aufrufer muß Spoeicher freigeben
*/

char* substr1(const char* str, int start, int end)
{
    int len = strlen(str);
    char* ptr;
    /* Teste Parameter auf Plausibiliät */
    if (end>len) end = len;
    if (start>len) start = len;
    if (start>end || start<0 || end<0 ) return NULL;

    /* erzeuge substring */
    ptr = malloc(end-start+1);
    if (NULL == ptr) return ptr;
    strcpy(ptr, "");
    strncat(ptr, str+start, end-start+1);

    return ptr;
}

/* Lösungsansatz 2: Der substring wird in static Speicher geschrieben.
   Vorteil: Kein free seitens der Aufrufers notwendig
   Nachteil: Nicht mutlithreading fähig, speicherloch
*/

char* substr2(const char* str, int start, int end)
{
    int len = strlen(str);
    /* Die folgenden Variablen MUESSEN static sein! */
    static char* ptr = NULL;
    static int size = 0;
    
    /* Teste Parameter auf Plausibiliät */
    if (end>len) end = len;
    if (start>len) start = len;
    if (start>end || start<0 || end<0 ) return NULL;
        
    /* ggf Speicher vergrößern */
    if (end-start+2>size || NULL==ptr)
    {
        char* tmp = realloc(ptr, end-start+2);
        if (NULL == tmp) return NULL;
        ptr = tmp;
        size = end-start+2;
    }

    strcpy(ptr, "");
    strncat(ptr, str+start, end-start+1);

    return ptr;
}

/* Lösungsansatz 3: Result Buffer mit übergeben
   Vorteil: wie 2
   Nachteil: Function schlägt bei zu keinem Buffer fehl; komplizierteres Interface
*/
  
char* substr3(const char* str, int start, int end, char* result, int size)
{  
    int len = strlen(str);
    /* Teste Parameter auf Plausibiliät */
    if (end>len) end = len;
    if (start>len) start = len;
    if (start>end || start<0 || end<0 ) return NULL;
    if (end-start+2>size) return NULL;

    strcpy(result, "");
    strncat(result, str+start, end-start+1);

    return result;
}  

int main()
{
    const char* str = "substring demo program";

    /* Anwenden ansatz 1 */
    {
        char* ptr = substr1(str, 1, 10);
        if (NULL != ptr)
        {
            printf("substr1(%s, 1, 10)=\"%s\"\n", str, ptr);
            free(ptr); /* unbedingt erforderlich! */
        }
    }

    /* Anwenden ansatz 2 */
    {
        char* ptr = substr2(str, 1, 10);
        if (NULL != ptr)
        {
            printf("substr2(%s, 1, 10)=\"%s\"\n", str, ptr);
        }
    }

    /* Anwenden ansatz 3 */
    {
        char result[20];
        char* ptr = substr3(str, 1, 10, result, sizeof(result));
        if (NULL != ptr)
        {
            printf("substr3(%s, 1, 10)=\"%s\"\n", str, ptr);
        }
    }
}



Tja. Oder man nimmt gleich C++: std::string hat schon eine methode substr.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
009
02.04.2003, 13:29 Uhr
Adi Suter



Danke, das funktioniert ja alles!!

Frage, wieso muss man bei dem ersten Lösungsansatz nach dem Aufruf noch den Speicher freigeben? Denn genau diese Zeile hat bei mir einen Programmfehler erzeugt. Lasse ich es weg, funktioniert's einwandfrei.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 < [ 2 ]     [ 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: