Anzeige:
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 15 von 16

Thema: C: String mit Pointer übergeben

  1. #1
    Registrierter Benutzer
    Registriert seit
    17.07.2007
    Beiträge
    38

    C: String mit Pointer übergeben

    Hallo,

    ich habe hier mal eine kleine Grundsatzfrage:
    Wenn ich ein char-Array ("normales" C) habe, kann ich dieses ja als String nutzen.

    Ich kann z.B. ein printf("%s\n",char_array) machen, wenn ich zuvor char char_array[16] deklariert habe.
    Wie kann ich so ein char array jetzt aber an eine Funktion mittels Pointer übergeben? Ist in meinem Fall nicht schon char_array (ohne die eckigen Klammern) ein Pointer? Da bin ich noch nie wirklich durchgestiegen...

    Wie müsste also eine Funktion aussehen, der ich so ein char array übergebe und wie würde der Aufruf aussehen?

    Klingt jetzt wahrscheinlich verwirrend, aber da ich selber vom Thema verwirrt bin, konnte ich das jetzt nicht strukturierter formulieren

  2. #2
    Registrierter Benutzer Avatar von peschmae
    Registriert seit
    14.03.2002
    Ort
    Schweizland
    Beiträge
    4.549
    char_array ist die Adresse vom Array. Insofern ähnlich einem Pointer; aber doch keiner weil du die natürlich nicht ändern kannst

    Funktion so:
    Code:
    void f1(char* );
    void f2(char[]);
    void f3(char[16]);
    Gehen alle. Die ersten beiden sind vollkommen äquivalent. Die letzte erwartet ein 16er Char-Array (oder alternativ einen cast...).

    Ich würde eins von den ersten beiden verwenden; die Länge des Char-Arrays ist dir in der Funktion ja prinzipiell egal da der String eh nullterminiert ist (ausser du willst da noch reinschreiben, aber dann lässt du dir die Länge besser explizit via einen zusätzlichen Parameter übergeben)

    Für so Array- und Pointergeschichten immer mal nett zum reingucken (insbesondere wenn das Array plötzlich mehrdimensional wird ): http://c-faq.com/aryptr/index.html

    MfG Peschmä
    The greatest trick the Devil ever pulled was convincing the world he didn't exist. -- The Usual Suspects (1995)
    Hey, I feel their pain. It's irritating as hell when people act like they have rights. The great old one (2006)

  3. #3
    Registrierter Benutzer
    Registriert seit
    17.07.2007
    Beiträge
    38
    Wenn ich das char array als Pointer übergebe ist die Länge doch eigentlich eh egal, weil die ja bereits in einer anderen Funktion definiert habe?!
    Wie verhält sich das grundsätzlich eigentlich mit Strings in C, wenn ich einen String über "char *string" deklariere, hat der dann automatisch eine bestimmte Länge oder muss ich das noch festsetzen? Sonst kommt es ja eigentlich leicht zu zugriffen auf "fremde" Speicherbereiche wenn der String zu lang wird?!

    Die Frage ist wahrscheinlich blöd, aber ich habe noch nicht viel Erfahrung mit C und vor allem wenig mit Strings in C.

  4. #4
    Registrierter Benutzer Avatar von ContainerDriver
    Registriert seit
    10.01.2003
    Beiträge
    418
    Zitat Zitat von shutdown Beitrag anzeigen
    Wenn ich das char array als Pointer übergebe ist die Länge doch eigentlich eh egal, weil die ja bereits in einer anderen Funktion definiert habe?!
    Wie und wo genau hast du die Länge "definiert"? Wenn du einen Pointer auf das Array an die Funktion übergibst, dann weiß die Funktion nichts von der Länge des Arrays (die Funktion kann diese nur herausfinden, wenn sie bis zum Null-Byte ('\0') im Array geht)!

    Wie verhält sich das grundsätzlich eigentlich mit Strings in C, wenn ich einen String über "char *string" deklariere, hat der dann automatisch eine bestimmte Länge oder muss ich das noch festsetzen? Sonst kommt es ja eigentlich leicht zu zugriffen auf "fremde" Speicherbereiche wenn der String zu lang wird?!
    Mit "char *string" definierst du nur einen Pointer, keine Länge. Anders wäre folgendes:
    Code:
    //Pointer auf den String "Hallo\0", Inhalt darf nicht verändert werden
    char *ptr="Hallo";
    
    //Anlegen eines char-Arrays der Länge 6 (Null-Byte beachten)
    //   mit dem Inhalt "Hallo\0", Inhalt darf verändert werden
    char string[]="Hallo";
    Gruß, Florian
    Ein gebrechlich Wesen ist der X-Server.

  5. #5
    Registrierter Benutzer
    Registriert seit
    17.07.2007
    Beiträge
    38
    Zitat Zitat von ContainerDriver Beitrag anzeigen
    Code:
    //Pointer auf den String "Hallo\0", Inhalt darf nicht verändert werden
    char *ptr="Hallo";
    Wofür ist so ein String denn dann überhaupt zu gebrauchen? Eine Variable die nicht variabel ist, macht doch wenig Sinn?!

    Also um das Ganze zu verstehen brauche ich vielleich einfach mal ein funktionierendes Beispiel, wie müsste folgendes aussehen, um zu funktionieren:

    Code:
    char string1[]="String1;is;delmited;by;;\nand;has;a;newline;in;it";
    char string2[32];
    
    string2=strsep();
    Wenn du mir die Zeile mal richtig hinpacken könntest, damit ich meinen String entweder nach der Newline oder den ; zerlegen kann, wäre mir wahrscheinlich echt geholfen, weil ich die Sache im moment nicht verstehe und nicht funktionsfähig hinkriege (endet entweder mit einem Kompiler-Fehler wegen falschen Pointern oder einem Segfault...)

  6. #6
    Registrierter Benutzer Avatar von ContainerDriver
    Registriert seit
    10.01.2003
    Beiträge
    418
    Zitat Zitat von shutdown Beitrag anzeigen
    Wofür ist so ein String denn dann überhaupt zu gebrauchen? Eine Variable die nicht variabel ist, macht doch wenig Sinn?!
    Eine Variable dient ja erstmal nur dazu um einen Wert zu halten, Konstanten können auch schon Sinn machen (z.B. wenn du eine feste Ausgabe von einer Zeichenkette hast).

    Also um das Ganze zu verstehen brauche ich vielleich einfach mal ein funktionierendes Beispiel, wie müsste folgendes aussehen, um zu funktionieren:

    Code:
    char string1[]="String1;is;delmited;by;;\nand;has;a;newline;in;it";
    char string2[32];
    
    string2=strsep();
    Wenn du mir die Zeile mal richtig hinpacken könntest, damit ich meinen String entweder nach der Newline oder den ; zerlegen kann, wäre mir wahrscheinlich echt geholfen, weil ich die Sache im moment nicht verstehe und nicht funktionsfähig hinkriege (endet entweder mit einem Kompiler-Fehler wegen falschen Pointern oder einem Segfault...)
    Hast du schonmal in die Manpage zu strtok geschaut, da steht ein gutes Beispiel:
    Code:
    EXAMPLE
           The following program uses nested loops that employ strtok_r() to break
           a string into a two-level hierarchy of tokens.  The first  command-line
           argument specifies the string to be parsed.  The second argument speci-
           fies the delimiter character(s) to be used to separate that string into
           "major"  tokens.   The  third  argument specifies the delimiter charac-
           ter(s) to be used to separate the "major" tokens into subtokens.
    
    
           #include <stdio.h>
           #include <stdlib.h>
           #include <string.h>
    
           int
           main(int argc, char *argv[])
           {
               char *str1, *str2, *token, *subtoken;
               char *saveptr1, *saveptr2;
               int j;
    
               if (argc != 4) {
                   fprintf(stderr, "Usage: %s string delim subdelim\n",
                           argv[0]);
                   exit(EXIT_FAILURE);
               }
    
               for (j = 1, str1 = argv[1]; ; j++, str1 = NULL) {
                   token = strtok_r(str1, argv[2], &saveptr1);
                   if (token == NULL)
                       break;
                   printf("%d: %s\n", j, token);
    
                   for (str2 = token; ; str2 = NULL) {
                       subtoken = strtok_r(str2, argv[3], &saveptr2);
                       if (subtoken == NULL)
                           break;
                       printf(" --> %s\n", subtoken);
                   }
               }
    
               exit(EXIT_SUCCESS);
           } /* main */
    
     An example of the output produced by this program is the following:
    
           $ ./a.out 'a/bbb///cc;xxx:yyy:' ':;' '/'
           1: a/bbb///cc
                    --> a
                    --> bbb
                    --> cc
           2: xxx
                    --> xxx
           3: yyy
                    --> yyy
    Kannst du damit was anfangen?
    Ein gebrechlich Wesen ist der X-Server.

  7. #7
    Registrierter Benutzer
    Registriert seit
    17.07.2007
    Beiträge
    38
    Das Beispiel ist ganz gut, nur wie funktioniert das ganze mit Arrays?

    Und nochmal zum Anfangsproblem:
    Code:
    int my_function(char string[])
    {
      [...]
    }
    führt zu folgendem Compiler-Fehler: "expected ‘;’, ‘,’ or ‘)’ before ‘string’"

    und
    Code:
    int my_function(char[] string)
    {
      [...]
    }
    führt zu "array type has incomplete element type"

    Wie übergebe ich das Array an eine andere Funktion? Vielleicht bin ich heute auch einfach nur zu blöd bzw vernagelt um das voll zu kapieren...

  8. #8
    Registrierter Benutzer Avatar von ContainerDriver
    Registriert seit
    10.01.2003
    Beiträge
    418
    Zitat Zitat von shutdown Beitrag anzeigen
    Das Beispiel ist ganz gut, nur wie funktioniert das ganze mit Arrays?
    Wie mit Arrays? Das Beispiel ist doch mit Arrays?


    Und nochmal zum Anfangsproblem:
    Code:
    int my_function(char string[])
    {
      [...]
    }
    führt zu folgendem Compiler-Fehler: "expected ‘;’, ‘,’ or ‘)’ before ‘string’"

    und
    Code:
    int my_function(char[] string)
    {
      [...]
    }
    führt zu "array type has incomplete element type"
    Die zweite Schreibweise ist definitiv falsch, die erste sollte hinhauen, evtl. ist da ein Fehler vor der Funktionsdefinition (poste doch mal den ganzen Code)?

    Minimalbeispiel:
    Code:
    [...]
    void func(char str*)
    {
        printf("%s\n",str);
    }
    
    [...]
    char *ptr="Hallo Welt";
    char str[]="Hallo Welt";
    func("Hallo Welt");
    func(ptr);
    func(str);
    [...]
    Ein gebrechlich Wesen ist der X-Server.

  9. #9
    Registrierter Benutzer
    Registriert seit
    17.07.2007
    Beiträge
    38
    Code:
    EXAMPLE
           The following program uses nested loops that employ strtok_r() to break
           a string into a two-level hierarchy of tokens.  The first  command-line
           argument specifies the string to be parsed.  The second argument speci-
           fies the delimiter character(s) to be used to separate that string into
           "major"  tokens.   The  third  argument specifies the delimiter charac-
           ter(s) to be used to separate the "major" tokens into subtokens.
    
    
           #include <stdio.h>
           #include <stdlib.h>
           #include <string.h>
    
           int
           main(int argc, char *argv[])
           {
               char *str1, *str2, *token, *subtoken;
               char *saveptr1, *saveptr2;
               int j;
    
               if (argc != 4) {
                   fprintf(stderr, "Usage: %s string delim subdelim\n",
                           argv[0]);
                   exit(EXIT_FAILURE);
               }
    
               for (j = 1, str1 = argv[1]; ; j++, str1 = NULL) {
                   token = strtok_r(str1, argv[2], &saveptr1);
                   if (token == NULL)
                       break;
                   printf("%d: %s\n", j, token);
    
                   for (str2 = token; ; str2 = NULL) {
                       subtoken = strtok_r(str2, argv[3], &saveptr2);
                       if (subtoken == NULL)
                           break;
                       printf(" --> %s\n", subtoken);
                   }
               }
    
               exit(EXIT_SUCCESS);
           } /* main */
    
     An example of the output produced by this program is the following:
    
           $ ./a.out 'a/bbb///cc;xxx:yyy:' ':;' '/'
           1: a/bbb///cc
                    --> a
                    --> bbb
                    --> cc
           2: xxx
                    --> xxx
           3: yyy
                    --> yyy
    Die Strings hier sind doch keine Arrays?!? (Hab mal fett markiert was ich meine)

    Hier mal noch mein Problemfall:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    void my_function(char string[][])
    {
      printf("%s\n",string[1]);
    }
    
    int main()
    {
      char test[3][8];
      test[1][0]='T';
      test[1][1]='E';
      test[1][2]='S';
      test[1][3]='T';
      test[1][4]='\0';
    
      printf("%s\n",test[1]);
    }
    Geändert von shutdown (09-07-2008 um 19:45 Uhr)

  10. #10
    Registrierter Benutzer Avatar von ContainerDriver
    Registriert seit
    10.01.2003
    Beiträge
    418
    Zitat Zitat von shutdown Beitrag anzeigen
    Die Strings hier sind doch keine Arrays?!? (Hab mal fett markiert was ich meine)
    Das sind Pointer (dienen als Hilfsvariablen), aber der String (also das was geparst werden soll) wird doch aus einem Array gelesen.
    Hier mal noch mein Problemfall:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    void my_function(char string[][])
    {
      printf("%s\n",string[1]);
    }
    
    int main()
    {
      char test[3][8];
      test[1][0]='T';
      test[1][1]='E';
      test[1][2]='S';
      test[1][3]='T';
      test[1][4]='\0';
    
      printf("%s\n",test[1]);
    }
    Willst du an my_function() ein zweidimensionales Array (also ein Array von Strings) übergeben oder einen einzelnen String? Nach der Zeile
    Code:
      printf("%s\n",string[1]);
    in my_function() vermute ich fast ersteres. Da würde ich dir diesen Link empfehlen: http://c-faq.com/aryptr/ary2dfunc3.html.
    Willst du doch nur einen einzelnen String übergeben müsste es heißen:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    void my_function(char string[])
    {
      //nicht string[1] UND %s verwenden!
      //wenn dann printf("%c\n",string[1]);
      //(Ausgabe des zweiten Zeichens)
      printf("%s\n",string);
    }
    
    int main()
    {
      char test[3][8];
      test[1][0]='T';
      test[1][1]='E';
      test[1][2]='S';
      test[1][3]='T';
      test[1][4]='\0';
    
      printf("%s\n",test[1]);
    }
    Ein gebrechlich Wesen ist der X-Server.

  11. #11
    Registrierter Benutzer
    Registriert seit
    17.07.2007
    Beiträge
    38
    Nein, da liegst du schon richtig - ich will das 2-dimensionale Array übergeben. Ich habe nur angenommen, dass Array Array ist und ich ein 2-dimensionales genauso wie ein 1-dimensonales übergeben kann.
    Aber da habe ich mich wohl geirrt und daher entstammen wohl auch die Probleme. Ich habs mal kurz mit dem 1-dimensionalen probiert, da klappt alles

    Ich lese mich da jetzt mal ein bisschen ein und seh mal, ob ich das Ganze evtl auch anders und einfacher lösen kann...zB indem ich auf das 2-dimensionale Array ganz verzichte.

  12. #12
    Registrierter Benutzer Avatar von ContainerDriver
    Registriert seit
    10.01.2003
    Beiträge
    418
    Um was für einen Arraytpen handelt es sich denn? Wenn die Größe des Arrays fest ist, dann spricht ja nichts gegen die Lösung void my_function(char (*array)[ELE_2_DIM]). Vielleicht kannst du das Array ja auch in eine Struktur stecken und dann einfach an die Funktion einen Pointer auf diese Struktur übergeben?
    Geändert von ContainerDriver (10-07-2008 um 09:07 Uhr)
    Ein gebrechlich Wesen ist der X-Server.

  13. #13
    Registrierter Benutzer
    Registriert seit
    17.07.2007
    Beiträge
    38
    Also ich hab mich jetzt nochmal rangemacht und die Sache glaube ich endlich geblickt

    Bleibt noch eine offene Frage:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
      char *costr="1;;3\n4;5;6\n7;8;9;\n";
      char str[strlen(costr)];
      strcpy(str,costr);
    
      char *line=NULL;
      char *val=NULL;
      char *ptr=NULL;
      char *ptr2=NULL;
    
      line=strtok_r(str,"\n",&ptr);
      while ( line != NULL )
      {
        printf("*** LINE: %s\n",line);
        val=strtok_r(line,";",&ptr2);
        while ( val != NULL )
        {
          printf("VALUE: %s\n",val);
          val=strtok_r(NULL,";",&ptr2);
        }
        line=strtok_r(NULL,"\n",&ptr);
      }
    
      return 0;
    }
    Das ist ein kleines Testprogramm von mir, der Output sieht folgendermaßen aus:
    Code:
    *** LINE: 1;;3
    VALUE: 1
    VALUE: 3
    *** LINE: 4;5;6
    VALUE: 4
    VALUE: 5
    VALUE: 6
    *** LINE: 7;8;9;
    VALUE: 7
    VALUE: 8
    VALUE: 9
    Wieso wird mir nach der Stelle, wo (wenn die Zahlenfolge die 2 enthalten würde) die 2 sein müsste, für diese Zeile noch etwas ausgegeben???
    Da er nichts ausgibt, nichteinmal ein "VALUE: " ohne Zahl, muss meine Variable val ja logischerweise gleich NULL sein (da das printf ja in der Schleife steht und in der Schleife keine Bedingung, die das printf auslassen könnte ist) - aber wenn man logisch weiterdenkt, müsste die innere while-Schleife in dem Moment aufhören zu laufen, da ja val == NULL.

    Ich habe da scheinbar ein logisches Denkproblem oder so...einerseits ist val NULL, andererseits aber gleichzeitig nicht!

    Sprich: Die Zeile "VALUE: 3" dürfte da eigentlich nicht stehen - da die Schleife abbrechen müssen hätte - oder es musste eine Zeile "VALUE: " oder "VALUE: (null)" (eigentlich auch nicht möglich - wegen dem Abbruch der Schleife in diesem Fall) vor der Zeile mit der 3 sein!

    Denkfehler oder seeeehr seltsam?
    Geändert von shutdown (09-07-2008 um 22:01 Uhr)

  14. #14
    Registrierter Benutzer Avatar von ContainerDriver
    Registriert seit
    10.01.2003
    Beiträge
    418
    Zitat Zitat von shutdown Beitrag anzeigen
    Also ich hab mich jetzt nochmal rangemacht und die Sache glaube ich endlich geblickt
    Schaut gut aus
    Bleibt noch eine offene Frage:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
      char *costr="1;;3\n4;5;6\n7;8;9;\n";
      char str[strlen(costr)];
      strcpy(str,costr);
    [...]
    Achtung: str muss die Länge strlen(costr) + 1 haben, da strlen() das Nullbyte nicht mitzählt (strlen("Hallo") = 5, es wird aber für 6 Zeichen Platz benötigt).


    Wieso wird mir nach der Stelle, wo (wenn die Zahlenfolge die 2 enthalten würde) die 2 sein müsste, für diese Zeile noch etwas ausgegeben???
    Da er nichts ausgibt, nichteinmal ein "VALUE: " ohne Zahl, muss meine Variable val ja logischerweise gleich NULL sein (da das printf ja in der Schleife steht und in der Schleife keine Bedingung, die das printf auslassen könnte ist) - aber wenn man logisch weiterdenkt, müsste die innere while-Schleife in dem Moment aufhören zu laufen, da ja val == NULL.

    Ich habe da scheinbar ein logisches Denkproblem oder so...einerseits ist val NULL, andererseits aber gleichzeitig nicht!

    Sprich: Die Zeile "VALUE: 3" dürfte da eigentlich nicht stehen - da die Schleife abbrechen müssen hätte - oder es musste eine Zeile "VALUE: " oder "VALUE: (null)" (eigentlich auch nicht möglich - wegen dem Abbruch der Schleife in diesem Fall) vor der Zeile mit der 3 sein!

    Denkfehler oder seeeehr seltsam?
    Ich glaube die Antwort dazu steht in der Manpage von strtok:
    A sequence of two or more contiguous delimiter characters in the parsed
    string is considered to be a single delimiter. Delimiter characters at
    the start or end of the string are ignored. Put another way: the
    tokens returned by strtok() are always non-empty strings.
    Gruß, Florian
    Ein gebrechlich Wesen ist der X-Server.

  15. #15
    Registrierter Benutzer
    Registriert seit
    17.07.2007
    Beiträge
    38
    Ok, bin da jetzt durchgestiegen denke ich - viel Dank für die Hilfe!

    Ein char-array ist eine Aneinanderreihung von chars und der Name des Arrays (ohne [x]) ist ein Pointer auf das erste char und kann deswegen wie ein char * benutzt werden, das auch nur ein Pointer ist - allerdings nicht mehr in die einzelnen chars "zerlegt" werden kann, da ja nur der Pointer selbst da ist. Deswegen kann man da auch nicht reinschreiben, da der Pointer ja wirklich nur eine Speicheradresse ist und selber keine Daten enthält (im Gegensatz zum char array, das eine Ansammlung von Daten ist).

    strtok() kann genau deswegen auch nur auf char arrays angewendet werden, da es lt. manpage die gesuchten Zeichen durch Null-Terminatoren ersetzt und nur einen Pointer auf das erste Zeichen des Strings bzw das erste Zeichen nach dem neu gesetzen Null-Terminator liefert.
    Logisch ist dadurch auch, das, wenn man diesen Fehler begeht, ein Segfault produziert wird, da ja nur ein Pointer und keine Daten da sind. (Wo nichts ist sollte man auch nichts reinschreiben, und wenn nur der Anfang des Strings bekannt ist, schreibt man viel zu leicht einen längeren String rein und würde dadurch in "fremden" Speicherbereichen landen)

    Soweit richtig erklärt? Wenn ja hab ichs wirklich geblickt

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •