write() aus einem string pointer



  • hallo,
    ich will einen string in eine datei schreiben, mittels write().

    bei einem char array wär das ja kein problem, weil man mittels sizeof() die grösse herausfinden kann und dann weiss, wieviele bytes man die write-funktion schreiben lassen soll.

    ich komm aber einfach nicht darauf, wie ich ermitteln kann,
    wie gross der String ist, wenn ich lediglich den Pointer darauf habe.

    was ich meine:

    int writeString(int fd, char *s){
    
    int stringSize;
    write(fd, s, stringSize);
    
    return 0;}
    

    ich hab also nicht das char array, sondern nur den pointer.
    wie finde ich stringSize heraus?

    ich wollte es in einer schleife machen und das array nacheinander durchlaufen.
    aber ich krieg speicherzugriffsfehler.
    mich wundert aber, dass ich da nen fehler krieg, denn es geht ja z.B. auch:

    printf(%c,s[0]);
    

    wieso geht dann aber nicht:

    while ((char)s[0] != 'a')
          {...}
    

    da bekomm ich wie gesagt speicherzugriffsfehler!

    Wäre dankbar für jede Hilfe, ich brauch wie gesagt den Wert von stringSize. 🕶



  • wie finde ich stringSize heraus?

    man: strlen(3)



  • jaaa okay darauf hätte ich auch kommen können, mal danach zu suchen... 🤡
    sorry..

    also es funktioniert jetzt schon, allerdings weiss ich noch immer nicht
    wirklich wie man mit diesen verfllixten char-array pointern umgeht.

    weil ich würde auch gerne noch mit diesem string dann ein paar sachen machen,
    eben z.B. in einer schleife alle darin vorkommenden characters mir anschauen usw.

    wie kann ich mit einem char array arbeiten, wenn ich nur den pointer darauf habe?

    z.B: wie überprüfe ich, ob der char 'x' in diesem String irgendwo vorkommt?

    danke



  • hdi07 schrieb:

    wie kann ich mit einem char array arbeiten, wenn ich nur den pointer darauf habe?
    z.B: wie überprüfe ich, ob der char 'x' in diesem String irgendwo vorkommt?

    char-arrays sind einfach eine folge von zeichen, die hintereinander im speicher liegen. das ende wird durch eine 0 gekennzeichnet und damit ist auch die länge bestimmt. wenn du ein 'x' suchen willst, dann fängste vorne an und guckst dir jedes zeichen an. triffst du auf die 0, dann bist du am ende angekommen und musst die suche abbrechen.
    🙂



  • wichtig: ein string im sinne von c wird mit \0 terminiert, dh: \0 ist das ende der gültigen werte in deinem string.

    char str[] = "Hallo"; // dann steht in deinem string H a l l o \0, es werden also 6 elemente reserviert.
    

    hdi schrieb:

    wie kann ich mit einem char array arbeiten, wenn ich nur den pointer darauf habe?

    also erstens: der name deines strings ist die konstante anfangsadresse des
    char-arrays, die vom typ char * ist, also sozusagen ein konstanter pointer auf
    einen char-wert. da du ein array von char deklarierst, werden die nachfolgenden
    array elemente direkt nach diesem char-wert im hauptspeicher angelegt und du kannst
    mit hilfe eines Indizes auf die nachfolgenden elemente verweisen. wenn du jetzt
    einer funktion diese anfangsadresse in einen pointer vom typ char * schreibst,
    kannst du in dieser genau gleich mit indizes auf den string zugreifen, weil dieser
    pointer den gleichen typen hat wie in der rufenden funktion, es steht also die
    gleiche anfangsadresse in den pointer als wie in der rufenden funktion. wenn du
    jetzt in deiner funktion werte in dem string veränderst, greifst du also auf den
    speicherbereich zu, den du in der rufenden funktion reserviert hast, dh: die
    änderungen erfolgen in dem string, den du in der rufenden funktion deklariert hast.

    hdi07 schrieb:

    weil der wert, der in x gespeichert ist größer als die dimension deines strings
    ist. (du greifst auf fremden speicher zu -> absturz)

    hdi07 schrieb:

    z.B: wie überprüfe ich, ob der char 'x' in diesem String irgendwo vorkommt?
    danke

    so:

    int i;
    for ( i = 0; str[i] != '\0'; i ++ )
    {
        if ( str[i] == 'x' )
        {
            // hier kommt x in deinen string vor!!!
        }
    }
    


  • nein genau das ist doch mein problem:

    ich habe NICHT das char array, sondern nur den POINTER darauf...

    kuck dir nochmal bitte meine funktion 'writeString' oben an...

    ich kann eben nicht auf einzelne chars in diesem String zugreifen über den Pointer, zumindest weiss ich nicht wie.



  • @ Gaste

    wir haben unsere posts gleichzeitig geschrieben 😉


    jedoch steht x nicht für die Stelle im Array, sondern für die Adresse oder?

    z.B. müsste ich dann str+1 testen, oder wenn der string aus integern besteht
    str+4 oder?



  • char string[...];
    char *pointer;
    ...
    pointer = string;  // jetzt kannst du mit dem pointer fast alles machen, was auch mit dem string geht.
    pointer[x] = '*';  // jetzt ist in string[x] das *
    

    und ausserdem: strlen(string) == strlen(pointer)
    🙂



  • hm, also sehr merkwürdig.

    genau das hab ich gemacht und habe speicherzugriffsfehler bekommen..

    manchmal versteh ich das nicht, ich mache sachen und sie gehen nicht,
    dann wird mir etwas gesagt was ich meiner meinung nach EXAKT so getan habe,
    es aber bei mir nicht ging, und dann geht's...
    oh man so n quatsch.. 🙄

    danke...



  • hdi07 schrieb:


    jedoch steht x nicht für die Stelle im Array, sondern für die Adresse oder?

    nein, x wird als index behandelt, also wenn x den wert 5 hast greifst du mit str[x]
    auf 6. arrayelement zu. (indizes fangen bei 0 an und gehen bis dimension - 1)

    mfg Gaste



  • okay danke, jetzt hab ich noch eine frage:

    die funktion writeString (siehe ganz oben in meinem programm)
    soll nur null-terminierte Strings annehmen.

    Ich frag mich aber, wie ich denn einen NICHT null-terminierten String
    übergeben kann??

    C hängt doch automatisch an jeden String ein '\0' an oder nicht?

    ein nicht-terminierter String wäre doch, wie ich mir das jetzt gedacht habe, nur ein TEIL eines Strings.

    Also wenn mein String z.B. 100 chars lang ist aber ich sag der write-Funktion, sie soll nur 10 byte schreiben. Dann hätte sie doch nen nicht-terminierten String oder?

    Aber eine Deklaration oder so eines gezielt NICHT null-terminierenden Strings gibt es doch nicht, oder?



  • hdi schrieb:

    Aber eine Deklaration oder so eines gezielt NICHT null-terminierenden Strings gibt es doch nicht, oder?

    gibt's nicht. wenn du den string kürzen willst, kannst du z.b. an position 11 eine 0 einsetzen. dann hat der string nur noch 10 zeichen.
    🙂



  • hdi schrieb:

    Aber eine Deklaration oder so eines gezielt NICHT null-terminierenden Strings gibt es doch nicht, oder?

    nein gibt es nicht. selbst wenn du so schreibst

    char str[10] = { 'H', 'a', 'l', 'l', 'o' };
    

    setzt der compiler alle restlichen werte im array auf 0.

    aber es könnte ja vorkommen, dass man aus versehen mal die terminierung überschreibt.



  • wie kann ich die Null-Terminierung überschreiben?

    So hab ich das versucht:

    char arr[] = "Hallo!";

    char *pointer;
    pointer = arr;

    pointer[6] = 'a'; // Überschreiben der Null-Terminierung ?!

    funktioniert aber nicht.

    statt dessen druckt er mir das 'a' sonst wo hin.
    Mir ist es passiert, dass ich zwei verschiedene Arrays hab mit jeweils nem Pointer drauf und wenn ich das gemacht habe da oben,
    dann hat sich das 'a' einfach an das ANDERE array angefügt 😮

    also wie geht sowas - nicht null-terminierter String ??



  • also sorry leute, ich will ja nicht rumnerven,
    aber bitte schaut euch DAS mal an !! WAS ZUM !?#* ist denn DA passiert?

    hier der code, ich bitte euch das anzukucken,
    weil das macht mir jetz richtig angst 😡

    meine funktion writeString:

    int writeString(int fd, char *s){
    
    	int stringSize = strlen(s);
    	if 	(s[stringSize] == '\0'){
    	if	(write(fd, s, stringSize) == -1)
    		{perror("@writeString: error in function write\n");
    		return EXIT_FAILURE;}
    		}
    	else	{perror("@writeString: error: String is not NULL-terminated\n");
    		return -1;}
    
    return 0;}
    

    und mein main-programm:

    int main (int argc, char *argv[]){
    
    char terminated[] = "Hallo Welt! Wie geht's dir so? ANTWORTE !!!\n";
    char nonTerminated[] = "Hallo Welt! Dieser String ist NICHT null-terminiert!";
    
    char *pointer, *pointerN;
    pointer = terminated;
    pointerN = nonTerminated;
    
    pointerN[52] = 'x';	// Überschreiben der Null-Terminierung!?
    
    printf("--------------- writeString: terminated ---------------\n");
    writeString(STDOUT_FILENO,pointer);
    
    printf("--------------- writeString: NOT terminated ------------\n");
    writeString(STDOUT_FILENO,pointerN);
    
    return 0;}
    

    so und hier nun meine absolut merkwürdige ausgabe auf der konsole beim aufruf:

    --------------- writeString: terminated ---------------
    Hallo Welt! Wie geht's dir so? ANTWORTE !!!

    --------------- writeString: NOT terminated ------------------
    Hallo Welt! Dieser String ist NICHT null-terminiert!xHallo Welt! Wie geht's dir so? ANTWORTE !!!

    was soll den der mist, dass er hier irgendwelche arrays aneinanderhängt ??

    ich weiss nur, dass es durch die zeile

    pointerN[52] = 'x';
    

    verursacht wird.

    also nochmal um meine andere frage zurückzukommen: wie überschreib ich denn ne null-terminierung?

    danke



  • hdi schrieb:

    so und hier nun meine absolut merkwürdige ausgabe auf der konsole beim aufruf:

    --------------- writeString: terminated ---------------
    Hallo Welt! Wie geht's dir so? ANTWORTE !!!

    --------------- writeString: NOT terminated ------------------
    Hallo Welt! Dieser String ist NICHT null-terminiert!xHallo Welt! Wie geht's dir so? ANTWORTE !!!

    was soll den der mist, dass er hier irgendwelche arrays aneinanderhängt ??

    ich weiss nur, dass es durch die zeile

    pointerN[52] = 'x';
    

    verursacht wird.
    danke

    also hier hast du im der main-funktion mit

    poitnerN[52] = 'x';
    

    die
    nullterminierung überschrieben. wichtig ist zu wissen, wie ein string ausgegeben
    wird: printf gibt die zeichen in einer schleife am bs aus. und zwar so lange,
    bis ein \0 auftritt. da du deine zwei strings in der main-funktion nacheinander
    deklariert hast, werden sie auch nacheinander im hautpspeicher angelegt. wenn du
    jetzt bei deinem 1. string die terminierung überschreibst, ist kein
    "ende" mehr vorhanden, und wenn du dann mit printf deinen string ausgeben
    willst, gibt er dir auch den nächsten string (der im hauptspeicher genau hinter
    dem 1. liegt) aus, weil er beim 1. kein \0 findet und so einfach weiter die
    zeichen ausgibt, bis er in deinem zweiten string ein \0 findet und dann die
    ausgabe beendet.

    hdi schrieb:

    int writeString(int fd, char *s){
    
    	int stringSize = strlen(s);
    	if 	(s[stringSize] == '\0'){
    	if	(write(fd, s, stringSize) == -1)
    		{perror("@writeString: error in function write\n");
    		return EXIT_FAILURE;}
    		}
    	else	{perror("@writeString: error: String is not NULL-terminated\n");
    		return -1;}
    
    return 0;}
    

    also die zeile if (s[stringSize] == '\0') ist sinnlos, weil dieser ausdruck
    IMMER true sein wird. funktionsweise von strlen: strlen zählt die zeichen von
    dem anfang deines strings bis zum 1. auftreten eines \0. dh: wenn du deine
    terminierung überschrieben hast, zählt strlen solange weiter, bis es ein \0
    findet. → s[stringSize] wird also IMMER \0 sein.

    mfg Gaste



  • vielen dank gaste !!!
    jetz versteh ich die arbeitsweise davon auf jeden fall besser 🙂

    aber: wie realisier ich das dann, dass die funktion writeString() checkt,
    ob der String null-terminierend ist?
    ich muss das irgendwie abfangen... in einer for-schleife? aber wie weit soll ich zählen, strlen darf ich ja nicht benutzen weil es eh weitersucht bis er ein '\0' findet.



  • zum überprüfen gibt es nur eine möglichkeit: du übergibst deiner funktion eine
    weitere int-variable, die die dimension (= maximale länge des strings, bei char
    str[25] ist sie 25, bei char str[100] = 100) enthält. dann überprüfst du so ob der
    string terminiert ist:

    if ( stringLength > maxLength ) // dann ist der string nicht nullterminiert
    

    diese lösung ist aber nicht so gut, da es möglicherweise die länge nicht bekannt ist. es ist besser du lässt die abfrage weg und nimmst an, das der benutzer der
    write-funktion einen nullterminierten string übergibt.

    mfg Gaste



  • ich weiss leider weder die länge, noch kann ich davon ausgehen, dass der benutzer das richtig macht.
    ist leider so...
    aber es MUSS doch irgendwie gehen oder?


Anmelden zum Antworten