Frage zu strncpy



  • Hallo zusammen,
    wie benutze ich den strncpy richtig ?
    Habe ein Funktion der zwei char Zeiger übergeben werden.
    Der erste Zeiger zeigt auf einen String, welcher in der Funktion gesplittet wird.
    Der zweite Zeiger zeigt auf einen Adressbereich, in den der gesplittete String geschrieben werden soll:

    int TestFunc(char *input,char *output) {
    
    	//String wird gesplittet und Ergebnis soll in den Adressbereich, auf den output zeigt, geschrieben werden
    	//buf enthält den gesplitteten String
    	strncpy(output,buf,strlen(buf)+1);
    	return 1;
    
    }
    

    Ein Bekannter von mir meinte jetzt aber zu mir das diese Benutzung von strncppy falsch sei, konnte mir aber nicht sagen wieso weshalb warum.
    Wie müsste ich den strncpy richtig benutzen, in dem Fall, damit der String richtig terminiert wird.
    Vielen Dank und beste Grüße



  • Vom Prinzip her ist das schon richtig. Es macht nur überhaupt keinen Sinn. Da Du auf jeden Fall den gesamten buf kopierst, könntest Du genausogut (vielmehr genauso schlecht!) einfach strcpy benutzen.
    Der eigentlich Sinn von strncpy besteht ja darin, die zu kopierende Anzahl von Zeichen am Platz im Ziel auszurichten.



  • Question0506 schrieb:

    Wie müsste ich den strncpy richtig benutzen, in dem Fall, damit der String richtig terminiert wird.

    Du musst im dritten Parameter angeben, wie groß output ist. Und falls buf zu groß für output ist, musst du beachten, dass output nicht nullterminiert ist.



  • Ein Bekannter von mir meinte jetzt aber zu mir das diese Benutzung von strncppy falsch sei, konnte mir aber nicht sagen wieso weshalb warum.

    ... ist natürlich schon brilliant. Auf so unqualifizierte Aussagen würde ich an deiner Stelle nicht hören. Das einizge was mir dazu einfällt wäre:
    strncpy_s statt strncpy zu nutzen, um die ganze Sache ein bisschen besser abzusichern.
    http://msdn.microsoft.com/de-de/library/5dae5d43.aspx

    Ansonsten sieht es meines Erachtens richtig aus ... bis auf dieses "+1" bei "strlen(buf)+1". Dort kopierst du ein Feld mehr, als dein Quellbuffer lang ist? Falls das wegen dem Terminierungszeichen sein sollte, s. unten.

    Zu der NULL-Terminierung steht in der Doku (Link s. oben):

    Wenn diese D-Zeichen in strDest passen (dessen Größe als numberOfElements angegeben ist) und noch Platz für einen NULL-Terminator ist, dann werden diese Zeichen kopiert und ein abschließendes NULL-Zeichen wird angefügt.

    ... sollte somit auch keine Probleme geben.



  • @My2Cents
    Sorry, aber du schreibst Mist.

    Der Funktion TestFunc ist die Größe von output nicht bekannt, also kann er strncpy_s nicht einsetzen.
    Wenn es bekannt ist, kann er die Funktionalität auch mit strncpy und etwas Zusatzcode (setzten des Terminators) erreichen.

    @Question0506
    So wie du es benutzt, wiegt dich das strncpy in falscher Sicherheit, da strcpy dasselbe macht.



  • MFK schrieb:

    Question0506 schrieb:

    Wie müsste ich den strncpy richtig benutzen, in dem Fall, damit der String richtig terminiert wird.

    Du musst im dritten Parameter angeben, wie groß output ist. Und falls buf zu groß für output ist, musst du beachten, dass output nicht nullterminiert ist.

    D.h. der String müsste dann explizit nochmal manuell terminiert werden ?

    Ansonsten sieht es meines Erachtens richtig aus ... bis auf dieses "+1" bei "strlen(buf)+1". Dort kopierst du ein Feld mehr, als dein Quellbuffer lang ist? Falls das wegen dem Terminierungszeichen sein sollte, s. unten.
    

    Habe mir mal die Doku durchgelesen. Das heißt am besten strncpy_s nutzen ?

    strncpy_S(Output,sizeOutput,buf,strlen(buf));
    


  • Da hast Du was Wichtiges weggelassen:
    "D ist dabei geringer an count und die Länge von strSource. Wenn diese D-Zeichen in strDest passen ..."
    Im Code des TE ist D aber die Länge der Quelle.



  • ne, einfach:

    strncpy(output,buf,sizeOfOutput - 1);
    

    Du musst halt wissen, wieviel Platz in output ist ...



  • Belli schrieb:

    ne, einfach:

    strncpy(output,buf,sizeOfOutput - 1);
    

    Du musst halt wissen, wieviel Platz in output ist ...

    Ok, dazu hatte ich auch noch das folgende gefunden:

    Copies the first num characters of source to destination. If the end of the source C string (which is signaled by a null-character) is found before num characters have been copied, destination is padded with zeros until a total of num characters have been written to it.

    No null-character is implicitly appended at the end of destination if source is longer than num. Thus, in this case, destination shall not be considered a null terminated C string (reading it as such would overflow).

    Wie kann ich das aber in der Funktion anpassen, wenn ich nicht weiß wie groß Output ist ? Einen zusätzlichen Parameter übergeben der die Größe von Output enthält oder wie würdet ihr das machen ?
    Komme aus der VB Welt und habe ein paar Anlaufschwierigkeiten.



  • Question0506 schrieb:

    Habe mir mal die Doku durchgelesen. Das heißt am besten strncpy_s nutzen ?

    strncpy_S(Output,sizeOutput,buf,strlen(buf));
    

    Nein, weil das Verhalten ein ganz anderes ist, wenn sizeOutput < strlen(buf) ist.

    Was willst du denn überhaupt damit erreichen?



  • Belli schrieb:

    strncpy(output,buf,sizeOfOutput - 1);
    

    Danach noch ein

    output[sizeOfOutput - 1] = '\0';
    

    da im Grenzfall die '\0' nicht geschrieben wird.

    Question0506 schrieb:

    Wie kann ich das aber in der Funktion anpassen, wenn ich nicht weiß wie groß Output ist ? Einen zusätzlichen Parameter übergeben der die Größe von Output enthält oder wie würdet ihr das machen ?

    Ja, das ist grundsätzlich immer zu empfehlen.



  • Jau, 0 anhängen hab ich vergessen, shame on me ...
    @TE: Du musst die Größe von output wissen, weil Du sonst Gefahr läufst, Speicher zu beschreiben, der Dir nicht gehört, egal, welche der genannten Funktionen Du benutzen willst.



  • Super vielen Dank.
    Leider habe ich im Netz in diversen Foren unterschiedliche Erklärungen gelesen.
    Hat sich nun soweit für mich geklärt.



  • Das wichtigste hast du ja selber erkannt:

    Question0506 schrieb:

    Einen zusätzlichen Parameter übergeben der die Größe von Output enthält

    Irgendwie sind die Funktionen blöd implementiert.
    strncopy vergisst die '\0' beim erreichen von n
    strncat bezieht das n auf die Quelle und nicht auf das Ziel
    strncpy _s macht noch mehr als nur "nicht zuviel" kopieren. Wenn nicht genug Platz ist, bleibt das Ziel leer. Auch wird auf NULL-Zeiger überprüft.

    Wenn du daran denkst, dass du die Arraylängen hast, kannst du den Rest auch mit Standardfunktionen machen. Du musst halt die Längenangaben berechnen.

    Oder du schreibst dir selber neue Funktionen dafür.

    Achja, eine Möglichleit geht noch:

    *output = '\0'; // erst den String "löschen"
    strncat(output,buf,sizeOfOutput-1);  // und dann anhängen
    

    Ist aber auch nicht besser als strncpy mit abschließender '\0' 😞


Anmelden zum Antworten