Kombinieren directory-und file-path - C
Als Teil des Lernens C, schrieb ich den folgenden code zu kombinieren-Verzeichnis-Namen mit der Datei Namen. Eg: combine("/home/user", "filename")
führt /home/user/filename
. Diese Funktion wird voraussichtlich auf allen Plattformen funktionieren (atleast auf allen gängigen linux-Distributionen und windows-32-und 64bit).
Hier ist der code.
const char* combine(const char* path1, const char* path2)
{
if(path1 == NULL && path2 == NULL) {
return NULL;
}
if(path2 == NULL || strlen(path2) == 0) return path1;
if(path1 == NULL || strlen(path1) == 0) return path2;
char* directory_separator = "";
#ifdef WIN32
directory_separator = "\\";
#else
directory_separator = "/";
#endif
char p1[strlen(path1)]; //(1)
strcpy(p1, path1); //(2)
char *last_char = &p1[strlen(path1) - 1]; //(3)
char *combined = malloc(strlen(path1) + 1 + strlen(path2));
int append_directory_separator = 0;
if(strcmp(last_char, directory_separator) != 0) {
append_directory_separator = 1;
}
strcpy(combined, path1);
if(append_directory_separator)
strcat(combined, directory_separator);
strcat(combined, path2);
return combined;
}
Habe ich die folgenden Fragen in Bezug auf den obigen code.
- Betrachten Sie die Zeilen nummeriert 1,2,3. Alle diese 3 Zeilen sind für immer das Letzte element aus dem string. Wie es aussieht, bin ich mehr code schreiben für so ein kleines Ding. Was ist die richtige Methode, um das Letzte element aus der
char*
string. - Das Ergebnis zurückgeben, ich bin die Zuweisung in einen neuen string mit
malloc
. Ich bin nicht sicher, ob dies der richtige Weg, dies zu tun. Aufrufer erwartet, dass free das Ergebnis? Wie kann ich an den Anrufer, dass er kostenlos das Ergebnis? Gibt es eine weniger fehleranfällige Methode zur Verfügung? - Wie beurteilen Sie den code (gering, Mittel, Gut)? Was sind die Bereiche, die sein können, verbessertes Wohlbefinden?
Jede Hilfe wäre toll.
Bearbeiten
Behoben, alle die Probleme, die besprochen und umgesetzt werden die vorgeschlagenen änderungen übernommen. Hier ist der aktualisierte code.
void combine(char* destination, const char* path1, const char* path2)
{
if(path1 == NULL && path2 == NULL) {
strcpy(destination, "");;
}
else if(path2 == NULL || strlen(path2) == 0) {
strcpy(destination, path1);
}
else if(path1 == NULL || strlen(path1) == 0) {
strcpy(destination, path2);
}
else {
char directory_separator[] = "/";
#ifdef WIN32
directory_separator[0] = '\\';
#endif
const char *last_char = path1;
while(*last_char != '\0')
last_char++;
int append_directory_separator = 0;
if(strcmp(last_char, directory_separator) != 0) {
append_directory_separator = 1;
}
strcpy(destination, path1);
if(append_directory_separator)
strcat(destination, directory_separator);
strcat(destination, path2);
}
}
In der neuen version, Anrufer hat genügend Puffer und senden combine
Methode. Dies vermeidet die Verwendung von malloc
und free
Problem. Hier ist die Verwendung
int main(int argc, char **argv)
{
const char *d = "/usr/bin";
const char* f = "filename.txt";
char result[strlen(d) + strlen(f) + 2];
combine(result, d, f);
printf("%s\n", result);
return 0;
}
Anregungen für weitere Verbesserungen?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Und es ist ein Speicher-Leck:
Edit: Ihre neue code sieht besser aus. Einige kleinere stilistische änderungen:
;;
in Zeile 4.strlen(path2) == 0
mitpath2[0] == '\0''
oder nur!path2[0]
.last_char
, und verwenden Sieconst char last_char = path1[strlen(path1) - 1];
if(append_directory_separator)
zuif(last_char != directory_separator[0])
. Und so brauchen Sie nicht die variableappend_directory_separator
mehr.destination
ähnlichstrcpy(dst, src)
gibtdst
.Bearbeiten: Und Ihre Schleife für
last_char
hat eine bug: es gibt immer das Ende derpath1
, und so könnten Sie am Ende mit einem doppelten Schrägstrich //Ihre Antwort. (Aber Unix zu behandeln, wird dies als eine einzige slash, es sei denn, es ist am Anfang). Trotzdem, mein Vorschlag behebt dieses--das sehe ich ganz ähnlich ist jdmichal Antwort. Und ich sehe, dass Sie sich das richtige in Ihrem original - code (die ich zugeben, dass ich nur kurz auf-es war zu kompliziert für meinen Geschmack; Ihre neue code ist viel besser).Sowie zwei weitere, etwas-mehr subjektive, Meinungen:
stpcpy()
zu vermeiden, die Ineffizienz derstrcat()
. (Einfach eigene zu schreiben, wenn es sein muss.)strcat()
und die wie als unsicher. Ich denke jedoch, dass Ihre Nutzung ist hier völlig in Ordnung.free("bar")
. Die nicht eine Katastrophe. Aber es ist nicht definiert.path1
oderpath2
wenn der zweite parameter leer ist, ist es unbekannt, ob Sie frei werden sollte, ist der zurückgegebene Wert oder nicht. Guten Fang.last_char
ist im Vergleich um zu überprüfen, ob das Letzte Zeichen ist ein Trennzeichen.Warum nicht ersetzen Sie es mit dieser:
Wenn Sie möchten, zu berücksichtigen, für die Möglichkeit, mehrere Trennzeichen, die Sie verwenden können, die folgenden. Aber sicher sein, wenn die Aufteilung der kombinierte Zeichenfolge hinzufügen strlen(directory_separator) anstelle von nur 1.
Weniger Fehler-anfällig Methode wäre, um die Benutzer-geben Sie die Ziel-Puffer und dessen Länge, viel, wie
strcpy
funktioniert. Dies macht deutlich, dass Sie verwalten, zuordnen und freigeben von Speicher.Prozess scheint anständig genug. Ich denke, es gibt nur einige Besonderheiten, die bearbeitet werden können, meist mit Dingen in einer langweiligen Art und Weise. Aber Sie sind gut, Sie können bereits erkennen, dass geschehen, und um Hilfe bitten.
directory_separator
einechar
stattchar*
, wie verwende ich es instrcat
?strncat
nimmt, die die Anzahl der Elemente anfügen. Nur, es&directory_separator
mit einer Länge von 1.Dies ist, was ich verwenden:
Nur eine kleine Bemerkung, um zur Verbesserung Ihrer Funktion:
Windows unterstützt sowohl
'/'
und'\\'
Trennzeichen in Pfaden. So ich sollte in der Lage zu führen Sie die folgenden nennen:Einer Idee beim schreiben ein Multiplattform-Projekt könnte zu konvertieren
'\\'
zu'/'
bei allen Eingabe-Pfad (aus user-input geladenen Dateien,...), dann werden Sie nur zu tun haben mit'/'
Zeichen.Grüße.
Ein kurzer Blick zeigt:
//
Stil Kommentare, die ich in der Lage bin, um mein Programm zu kompilieren, die auf einem C-compiler. 2. Ich nicht an diesem Punkt. Warum sollte es definiert werden, die am Anfang der Funktion? Wieder dieser code kompiliert ohne Warnung./* */
Paare und Variablendeklarationen an der Spitze des Bereichs. Aber viele moderne Compiler verletzen beides auf einfache Programmierung. Das heißt, Sie akzeptieren//
Kommentare und wird automatisch neu anordnen Deklarationen von Variablen beim kompilieren.-ansi
durchsetzen wird entweder ISO-oder ISO-C89 C90-standards, die Fehler aus C++-style Kommentare.