2016-04-27 8 views
2

Ich dachte daran, eine Strenge Alternative mit dem Beenden von '\ 0' für meine eigene Verwendung in einer Header-Datei zu machen, und frage mich, welche der folgenden Ansätze besser wäre.strncpy() Alternative - welche Vorteile für jede Version?

int copystring(char *dest,char *source,int elements) 
{ 
    int run; 
    for(run=0;run<elements-1;run++)//last reserved for'\0' 
    { 
     dest[run]=source [run]; 
     if (dest[run]=='\0') 
     { 
      break; 
     } 

    } 
    dest[elements-1]='\0';//could make conditional but not neccesary. 
    return 0; 
} 

ODER

int copystring(char *dest,char *source,int elements) 
{ 
     strncpy(dest,source,elements-1); 
     dest[elements-1]='\0'; 
     return 0; 
    } 

Der offensichtliche Unterschied für mich ist, dass ich rufe eine weniger Funktion mit der Version, aber ich frage mich, ob Version zwei irgendwelche Vorteile hat, wie ich weiß nicht, die internen arbeiten von strncpy()

Als beiseite, warum nimmt strncpy() size_t als das letzte Argument? Wenn es um die Weitergabe von Werten geht, die nur in sehr begrenzten Situationen nützlich sein werden, würde ein Int nicht genauso gut funktionieren?

+1

Was ist das Erreichen dass 'strcopy' bieten nicht schon? Zusätzlich, warum brauchen Sie die Länge einer 'char * Quelle mit Null-Ende' um es zu kopieren? – CollinD

+0

Es hat Pufferüberlaufschutz für das Ziel. Ich werde 'Elemente' verwenden, um die maximale Ziellänge zu übergeben. – Orangesandlemons

+0

BTW: 'dest [run + 1] = '\ 0';' - >> 'dest [run] = '\ 0';' (run wird bereits nach der Schleife inkrementiert) – wildplasser

Antwort

2

Der einfachste Ersatz für strncpy() (wenn Sie das Gefühl, dass man einen braucht) ist wahrscheinlich die:

dest[0] = '\0'; 
strncat(dest, source, size); 

strncat(), im Gegensatz zu strncpy(), garantiert, dass das Ziel richtig nullterminierte ist, und keine zusätzliche kopiert Nullbytes, wenn das Ziel größer als die Quelle ist.

Aber stellen Sie sicher, dass dieses Verhalten wirklich das ist, was Sie wollen. Wenn Sie strcpy() verwenden und das Zielarray nicht groß genug ist, erhalten Sie undefiniertes Verhalten. Mit strncpy oder strncat erhalten Sie ein definiertes Verhalten: Der Wert wird ruhig abgeschnitten. Wenn es das ist, was du willst, großartig - aber es ist selten. Häufiger erhalten Sie durch das Abschneiden von Daten nur schlechte Daten, und Sie sollten es erkennen und als Fehler behandeln, statt Procusus alles zu verwerfen, was nicht passt. (Imaging Kürzen "rm -rf $HOME/unimportant_directory"-"rm -rf $HOME", bevor es zu system() vorbei.)

Als Nebenwirkung nicht, warum size_t als das letzte Argument strncpy() nehmen? wenn es ist für die Weitergabe von sizeof Werte, die nur in sehr begrenzten Umständen nützlich sein, würde nicht ein int genauso gut tun?

size_t macht nur mehr Sinn, da es der Typ ist, der verwendet wird, um Größen und Längen darzustellen. Unter Verwendung von int müsste das Verhalten für negative Argumente definiert (oder nicht definiert) werden und könnte die Größe der Zeichenfolge begrenzen, die Sie verarbeiten könnten (wenn z. B. int 16 Bits und size_t 32 Bits ist). Sie können immer einen Wert von int übergeben, der implizit in size_t konvertiert wird.

Eine weitere Option ist die nicht standardmäßige strlcpy()-Funktion. Es ist nicht auf allen Systemen verfügbar, aber Sie sollten es installieren können (zum Beispiel mit dem libbsd-dev Paket für Debian/Ubuntu/... Systeme) oder es von der Quelle erstellen.

Übrigens, hier ist mein rant zum Thema strncpy():
http://the-flat-trantor-society.blogspot.com/2012/03/no-strncpy-is-not-safer-strcpy.html

+0

Mein Plan ist, die Zeichenfolge weiter zu lesen, bis das Ende erreicht ist (aber nicht in ein Array), und dann diese Zahl als Funktion return zurückgibt, was eine benutzerdefinierte Fehlerbehandlung je nach Bedarf ermöglicht. Natürlich, wenn ich alle Characers brauche, muss ich dynamisch zuweisen – Orangesandlemons

+1

Hinweis: wichtig, dass "Größe" nicht die Größe des Raumes überschreitet, auf den "dest" zeigt. 2) BTW: gute Wahl zwischen OPs 2 Optionen: weder – chux

+0

Ein Nachteil davon ist, dass es erforderlich wäre, dest [0] mit '\ 0' zu initialisieren, während ich idealerweise so wenig Code wie möglich hätte. Ich versuche immer noch, einen Weg zu finden, um meiner Funktion die Größe des Zielarrays in Fällen mitzuteilen, in denen ein Array zu einem Zeiger usw. verfallen ist. – Orangesandlemons