Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » strings an externe Funktionen

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
29.09.2002, 16:57 Uhr
Toby



Hallo,

ich habe ein paar kleine problemchen,
ich möchte in einer externen funktion
strings aus der aufrufenden main()
bearbeiten und dann das veränderte
an die main() zurückliefern.
mit zahlen kann ich es über pointer
so erledigen:

# include <stdio.h>

void change(int *zahl)
{
int plus=*zahl+1;
printf("%i + 1 = %i\n",*zahl,plus);
}

int main()
{
int zahl=5;
change(&zahl);
return (0);
}

wenn ich aber versuche bei externen funktionen,
auf strings aus der aufrufenend funktion zuzugreifen,
scheitert es:

# include <stdio.h>

void change(char *wort)
{
printf("das wort war: %s\n",*wort);
strcpy(wort,"klappt");
printf("das wort ist jetzt: %s\n",*wort);
}

int main()
{
char wort[10];
strcpy(wort,"blah");
change(wort);
return (0);
}

kann mir jemand zeigen, wie man es richtig macht?

Danke
Toby
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
29.09.2002, 17:55 Uhr
Bruder Leif
dances with systems
(Operator)


Moin!

Probiers mal ohne den Stern in den printf-Anweisungen! Du übergibst einen Zeiger auf char-Werte an die Funktion; wenn Du den jetzt per Stern dereferenzierst, wird ein einzelner char draus, printf sucht aber nach einem Zeiger...
--
Mit 40 Fieber sitzt man nicht mehr vor dem PC.
Man liegt im Bett.
Mit dem Notebook.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
29.09.2002, 21:33 Uhr
Toby



Hi,

yep, klappt. Danke!

Was ich aber nicht verstehe, warum bei integer man den "*" setzen muss und bei arrays nicht? Kann mir das jemand kurz erklären?

TIA
Toby
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
30.09.2002, 15:27 Uhr
fry_



Hallo,

das liegt an der Sonderstellung von Strings.

Erstmal etwas anderes:

Einmal, sind das nicht dieselben Variablen (weißt Du bestimmt)
in Deinem Beispiel.
int *zahl
int zahl

zahl -> void change(int *zahl)

Ist ein Zeiger vom Typ Integer, der auf die Aresse von

zahl -> int zahl=5;

zeigt. Um Missverständnisse zu vermeiden, sollte man den verschiedenen Variablen auch unterschiedliche Namen geben. zB.:
void change(int *z) // oder noch besser
void change(int *pZahl) // p für Pointer, oder
void change(int *zahl_ptr)

Ich ändere jetzt mal den Namen, damit man
es besser erklären kann.

C++:
void change(int *zahl_ptr)
{
        int plus=*zahl_ptr+1;
        printf("%i + 1 = %i\n",*zahl_ptr,plus);
}

int main()
{
int zahl=5;
change(&zahl);
return (0);
}


In zahl_ptr steht die Adresse von zahl.
printf("%i", zahl_ptr); -> gibt die Adresse von zahl aus.
Um jetzt aber über diesen Zeiger den Inhalt von zahl
zu verändern oder ihn anzeigen zu lassen, nimmt man den Dereferenzierungsoperator '*'.
printf("%i", *zahl_ptr); -> gib den Inhalt von zahl aus, nicht den
von zahl_ptr.

oder verändern:
int zahl=5;
int* zahl_ptr=&zahl;
*zahl_ptr=7; // Ich ändre nicht den Inhalt von zahl_ptr sonder durch das '*' den
von zahl.
printf("%i", zahl); -> 7

Die beiden '*' haben hier zwei verschiedene Bedeutungen. Das erste '*' mit Datentyp davor, ist ein Zeiger vom Typ Integer. Das letztere ein Dereferenzierungsoperator.

--


C++:
void change(char *s) // 's' -> der besseren Lesbarkeit wegen
{
        printf("das wort war: %s\n",s);
        strcpy(s,"klappt");
        printf("das wort ist jetzt: %s\n",s);
}

int main()
{
        char wort[10];
        strcpy(wort,"blah");
        change(wort);
        return (0);
}


printf("das wort war: %s\n",s);
Hier übergibst Du auch die Adresse(bzw. Startadresse, weil wort ein String ist) an printf.
Nur printf merkt, dass es sich um ein String handelt u. gibt nicht die Startadresse von wort aus sonder gleich alle Zeichen. Wenn Du das jetzt
so '*s' schreibst, verhält es sich wie ein Integer u. gibt nur den
Inhalt der Startadresse von wort aus -> b

Damit du mit den Bezeichnungen nicht durcheinander kommst:
Das ist ein Array
Int zahl[4];

das auch
char wort[4]={'b','l','a','h'}; // -> 4 Zeichen groß

Jetzt wird daraus ein Sring
char wort[5]={'b','l','a','h','\0'}; // Endkennung '\0' -> 5 Zeichen groß

So geht es auch
char wort="blah" // -> 5 Zeichen groß, die '\0' musst Du Dir am Ende denken

So, ich hoffe, dass ich Dir ein bisschen helfen konnte.

Gruß
--
mit computern geht alles viel schneller
es dauert nur ein bisschen länger

Dieser Post wurde am 30.09.2002 um 15:54 Uhr von fry_ editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
03.10.2002, 17:53 Uhr
~Toby
Gast


Hi fry_,

danke für Deine Erklärungen. Ich musste ich es mehrere Male lesen, um es endlich zu verstehen. Die pointer sind für nen Anfänger wie ich ziemlich verwirrend, da dort ziemlich abstrakt mal mit den Speicherstellen, mal mit den Inhalten jongliert wird. Für Euch ist es unverständlich, wie man es nicht verstehen kann, aber ich musste sehr lange dran knabbern und bin mir auch jetzt immer noch nicht so sicher, ob ich das richtig verstanden habe. Da aber Pointerverständnis (hab ich mal gehört) in C ziemlich das wichtigste ist, möchte ich es auch sicher beherschen. Ich hab also mir ein kleines progy erstellt, was mir die Zusamenhänge nochmal verdeutlichen sollte:

# include <stdio.h>

int main (void)
{
int a=5,*a_ptr;

a_ptr=&a;

printf("inhalt von 'a' ist %i\n",a);
printf("die adresse von 'a' ist '&a' = %i\n",&a);
printf("pointer '*a_ptr' hat die adresse von 'a' gespeichert. inhalt von 'a_ptr' ist also %i\n",a_ptr);
printf("inhalt der speicherstelle wo '*a_ptr' zeigt ist = %i\n",*a_ptr);

return (0);
}

Habe ich es richtig dargestellt und verstanden?
Danke
Toby
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
03.10.2002, 19:46 Uhr
fry_



Hi Toby

Super, wie gut du das verstanden hast! Ist manchmal wirklich nicht so einfach, das stimmt schon. Noch was: Adressen lassen sich gut mit %p anzeigen -> hatte ich nicht dran gedacht.

Ok, bis dahin.

Gruß

P.S.
"...pointer '*a_ptr' hat die adresse von 'a' gespeichert..."
-> pointer 'a_ptr' hat die adresse von 'a' gespeichert
(hast Du Dich noch verschrieben)
--
mit computern geht alles viel schneller
es dauert nur ein bisschen länger

Dieser Post wurde am 03.10.2002 um 20:04 Uhr von fry_ editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
04.10.2002, 23:01 Uhr
~Toby
Gast


Hi,

danke für die warmen Worte :) aber:

> "...pointer '*a_ptr' hat die adresse von 'a' gespeichert..."
> -> pointer 'a_ptr' hat die adresse von 'a' gespeichert
> (hast Du Dich noch verschrieben)

hmm, eigentlich dachte ich es wirklich mit "*" (asterisk?). Wie ist es also mit der Darstellungsweise von pointern? Ich dachte, erst dieses "*" vor dem Variablennamen macht das ganze zum Pointer... Dann habe ich gerade irgendwo nachgeschlagen, dass zb "int *" sagt, dass es eine pointervariable ist, aber dann habe ich also immer noch nicht verstanden, warum man vor dem Pointer auf strings [siehe Bsp oben: printf("das wort war: %s\n",wort);] keinen "*" davor setzen soll und zum gegensatz bei pointern auf integervariablen muss man das "*" setzen [siehe Bsp oben: printf("%i + 1 = %i\n",*zahl,plus);]???

Kann mir das jemand erklären? :)
Danke
Toby, der jetzt doch wieder ganz verwirrt wurde :(
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
007
06.10.2002, 15:56 Uhr
fry_



Hallo Toby


Zitat:

Ich dachte, erst dieses "*" vor dem Variablennamen macht das ganze zum Pointer


Nein, NUR wenn auch noch vor dem '*' wiederum ein Datentyp steht
-> int* a_ptr

Diese verkürzte Schreibweise in Deinem Beispiel hat Dich vielleicht verwirrt:
int a=5,* a_ptr;

Sowohl 'a' wie auch '*a_ptr' benutzen den einen Datentyp 'int'. Man beachte das ',' nach der 5.

Eigentlich steht dort:
int a=5; int* a_ptr; <- Man beachte das ';' nach der 5.

Beide Schreibweisen sind völlig korrekt u. haben ein u. dieselbe Bedeutung.

WICHTIG:
Die beiden folgenden '*' haben zwei ganz unterschiedliche Bedeutungen.
'*' Variante 1:
int* a_ptr <- Durch diesen '*' (MIT Datentyp davor -> 'int*') erstelle ich mir den Pointer vom Typ Integer

a_ptr <- so wie er jetzt in dieser Codezeile dasteht, ist er ein Pointer vom Typ Integer, den ich in der Codezeile darüber erstellt habe.

a_ptr = &a; // Pointer a_ptr bekommt die Adresse von a zugewiesen.

'*' Variante 2: (betrachte es als Hilfsmittel für Pointer)
*a_ptr <- Mit diesem '*' (hier OHNE Datentyp davor -> '*') würde ich den Inhalt der variable bekommen, worauf der Pointer 'a_ptr'
zeigt(also den Inhalt von a)

Fazit: Variante 2 klappt nur, wenn a_ptr bereits ein Pointer IST! Ich erstelle mir somit kein Pointer!


Zitat:

aber dann habe ich also immer noch nicht verstanden, warum man vor dem Pointer auf strings
[siehe Bsp oben: printf("das wort war: %s\n",wort);] keinen "*" davor setzen soll und zum
gegensatz bei pointern auf integervariablen muss man das "*" setzen


Das liegt an der Sonderstellung von Strings:

Merke Dir doch einfach, sobald man den Inhalt von variablen mit '%s'
ausgeben kann, benötigt man kein '*'.
Wie:
Strings -> "char* ch="Hallo";

Möglich ist aber auch: (sieht aber nicht schön aus)
Zeichenkette vom Typ char -> char ch={'H','a','l','l','o'};

Zwei Beispiele:


C++:
#include <stdio.h>
// möglich wäre auch #include <cstdio>
// falls du das mal siehst

int main()
{

    // ARRAY UND POINTER
    int ix;        // Laufindex für die while-Schleifen
    int i[10];    // array mit Index 0-9
    int* pi;    // Zeiger vom Typ Integer

    // array i wird mit Werten gefüllt -> 95-86
    for (ix=0; ix<10; ++ix)
        i[ix]=95-ix;

    pi = &i[0];     // übergib die Adresse des ersten Elements im
                                      // array i (auch Startadresse)
    // verkürzte Schreibweise: pi = i;

//[1]
    printf("[1]\n");
    printf("%p\n",pi);    // die Adresse des ersten Elements im
                                      // array i

//[2]
    printf("[2]\n");
    printf("%i\n",*pi);    // der Inhalt des ersten Elements worauf
                                      // pi zeigt

//[3]
    printf("[3]\n");
    // gibt über den Pointer pi alle Adressen im array i aus
    while(pi!=&i[10]) { // bis er auf die Adresse nach der letzten
                                      // Adresse vom array i trifft
        printf("%p\n",pi++); // übergibt erst seinen Inhalt(eine
                                      // Adresse) u. geht dann eine Adresse im
                                      // array i weiter
    }

    // So am Rande -> Achte mal auf die Adressen:
    // In meinem Bsp:
    // 0012FF54
    // 0012FF58 +4
    // 0012FF5C +4
    // ...
    // Bei mir ist Integer 4 Byte(32Bits) groß, also liegen alle 4
             // Stellen auseinander
    // -> 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F

    pi = &i[0]; // setzt pi wieder auf die Startadresse vom array i

//[4]
    printf("[4]\n");
    // gibt über den Pointer pi den Inahlt aller Elemente im array
            // i aus
    while(pi!=&i[10]) {
        printf("%i\n",*pi++);
    }
            // Übergibt erst seinen Inhalt des Elements, worauf pi zeigt u.
            // geht dann eine Adresse im array i weiter(++).                            
           // ++ hat eine größere Bindungskraft als * -> daher benötigt
           // man nicht *(pi++) möchtest du aber den Inhalt um 1 erhöhen,
           // warauf pi zeigt -> (*pi)++ ;-)

/*
// STRING UND POINTER
    int ix;        // Laufindex für die while-schleife
    char s[10]; // array mit Index 0-9
    char* ps;     // Zeiger vom Typ char

    // füllt den array ch mit Zeichen
    for (ix=0; ix<10; ++ix)
        s[ix]=97+ix; // fängt im Ascii-code bei 'a' an

             // Das letzte Element bekommt die Endkennung '\0'
    s[9]='\0'; // Macht aus dem array s einen string

    ps = &s[0]; // übergibt die Startadresse im string s

//[1]
    printf("[1]\n");
    printf("%p\n",ps);     // zeigt den Inhalt des Pointers ps an
                                      //(Startadresse von s)

//[2]
    printf("[2]\n");
    printf("%c\n",*ps); // gibt den Inhalt des ersten Elements im
                                       // string aus

    // Gibt alle Adressen über den Pointer ps im string s aus

            while(ps!=&s[9]) {     // bis er auf Endkennung '\0' trifft
        printf("%p\n",ps++);// gibt erst den Inhalt von ps(eine
                                      //Adresse) an printf u. geht dann
                                      //eine Adresse im string s weiter(++).
    }

    // Bei mir:
    // 0012FF70
    // 0012FF71 +1
    // 0012FF72 +1
    // ...
    // char ist nur 1 Byte(8Bits) groß, also liegen alle Elemente
             //eine Stellen auseinander

    ps = &s[0];     // setzte ps wieder auf die Startadresse vom
                                      // string s

//[3]
    printf("[3]\n");
    // Wichtig: hier benötige ich keine Schleife mehr, um den
             // Inhalt aller Elemente im
    // string s über den Pointer ps auszugeben.

    printf("%s\n",ps);     // durch das %s weiß printf, dass es,
             // beginnend bei der Adresse, die
    // von ps übergeben wird, den Inhalt aller
            // Elemente ausgeben soll.

//[4]
    printf("[4]\n");
    // Du kannst es aber auch mit Hilfe einer Schleife ausgeben
             // (dann aber mit '*')
    // Gibt alle Zeichen über den Pointer ps vom string s aus
    while(ps!=&s[9]) {
        printf("%c\n",*(ps++)); // printf bekommt ein Zeichen
                                                          //(%c) u. kein ganzen string (%s)
    }*/


    return 0;
}


Frag' einfach noch mal, wenn etwas unklar ist.

Gruß
--
mit computern geht alles viel schneller
es dauert nur ein bisschen länger

Dieser Post wurde am 06.10.2002 um 16:07 Uhr von fry_ editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
008
11.10.2002, 01:26 Uhr
~Toby
Gast


wow! danke

ich muss es jetzt innerlich verarbeiten. Falls Fragen aufkommen, melde ich mich. Danke für das Angebot!

cu
Toby
 
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: