Dans le cadre de l'apprentissage C, j'ai écrit le code suivant pour combiner le nom du répertoire avec le nom de fichier. Par exemple: Voici le code. P> combine ("/ home / utilisateur", "nom de fichier") code> entraînera
/ home / utilisateur / nom_fichier code>. Cette fonction est attendue de travail entre toutes les plateformes (au moins sur toutes les distributions Linux populaires et Windows 32 et 64 bits).
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;
}
6 Réponses :
Un coup d'œil rapide montre: p>
Merci. Les commentaires du code sont juste pour une explication. Je ne l'ai pas sur le vrai code. Mais avec // code> Style Style, je suis capable de compiler mon programme sur un compilateur C. 2. Je n'ai pas eu ce point. Pourquoi devrait-il être défini au début de la fonction? Encore une fois ce code compile sans aucun avertissement.
Les deux premiers points sont corrects, en ce que ANSI C prend uniquement en charge les commentaires à l'aide de / * * / CODE> paires et déclarations variables en haut de la portée. Mais de nombreux compilateurs modernes violent ces deux pour faciliter la programmation. C'est-à-dire qu'ils acceptent les commentaires
// code> et réorganiseront automatiquement les déclarations variables lors de la compilation.
Les commentaires C ++ et les déclarations mélangées sont valables C99.
@jdmichal euh, un peu. Par "compilateurs modernes violer", vous voulez dire "compilateurs modernes adhérons au moins C99". Utilisation de -ansi code> appliquera les normes ISO C89 ou ISO C90, qui exerceront des commentaires de style C ++.
last_char code> est dans la comparaison pour vérifier si le dernier caractère est un séparateur. LI>
Pourquoi ne pas le remplacer par ceci: p> xxx pré> Si vous souhaitez rendre compte de la possibilité de plusieurs séparateurs de caractères, vous pouvez utiliser ce qui suit. Mais assurez-vous que lors de l'allocation de la chaîne combinée pour ajouter SHLEN (Directory_Separator) au lieu de 1. P> xxx pré>
-
La méthode Moins d'erreur d'erreur serait d'avoir l'utilisateur de vous donner le tampon de destination et sa longueur, autant de la manière Strcpy code> fonctionne. Cela indique clairement qu'ils doivent gérer alloué et libérer la mémoire. P> li>
-
Le processus semble assez décent. Je pense qu'il y a juste des détails qui peuvent être travaillés, principalement avec faire des choses de manière cluntée. Mais vous allez bien, en ce que vous pouvez déjà reconnaître que cela se passe et demander de l'aide. P> li>
ol> ol>
Merci. Si l'appelant fournit le tampon, comment il sait combien d'allouer? Bien entendu, l'appelant sait sur les deux chemins mais pas le séparateur de répertoires. Donc, je me demande, ce sera un bon choix? Toutes les autres suggestions sont excellentes. Très appréciée.
@Appu: à Unix, max_path_len est une taille de mémoire tampon raisonnable.
De même, Windows a un max_path, soit 260 caractères.
Si je fais répertoire_separator code> a
char code> au lieu de
char * code>, comment l'utiliser dans
strcat code>?
J'ai mis à jour le message avec le dernier code. S'il vous plaît jetez un coup d'oeil à nouveau.
Vous pouvez utiliser strncat code>, qui prend le nombre d'éléments à ajouter. Il suffit de lui donner
& annuaire_separator code> d'une longueur de 1.
Et il y a une fuite de mémoire: edit: strong> Votre nouveau code semble mieux. Quelques changements stylistiques mineurs: P> éditer em>: et votre boucle pour et deux autres, légèrement plus subjectifs, opinions: p>
;; code> dans la ligne 4. li>
strallen (chemin2) == 0 code> avec
chemin2 [0] == '\ 0' ' code> ou juste
> chemin2 [0 ] code>. li>
last_char code> et utiliser
const charer_char = chemin1 [SHLEN (PATH1) - 1]; CODE> LI>
if (append_directory_separator) code> à
si (last_char! = Directory_Separator [0]) code>. Et donc vous n'avez pas besoin de la variable
append_directory_separator code> plus. LI>
Strcpy (dst, src) code>, qui retourne
dst code>. li>. LI>.
ul>
last_char code> a un bug em>: il renvoie toujours la fin de
path1 < / Code>, et vous pourriez donc vous retrouver avec une double slash // dans votre réponse. (Mais UNIX traitera cela comme une seule barre oblique, à moins que ce soit au début). Quoi qu'il en soit, ma suggestion corrige cela - ce que je vois est assez similaire à la réponse de Jdmichal. et em> je vois que vous avez eu raison dans votre code original em> (que j'avoue que je n'ai que jeté seulement à - c'était trop compliqué à mon goût; votre nouveau code est bien meilleur ). P>
stpcpy () code>, pour éviter l'inefficacité de
strcat () code>. (Facile à écrire le vôtre, si besoin est.) Li>
strcat () code> et similaire comme étant dangereux em>. Cependant, je pense que votre usage ici est parfaitement bien. Li>
ul> p>
Bon point. J'étais au courant des fuites. Mais la catastrophe était nouvelle pour moi. Pouvez-vous s'il vous plaît expliquer comment cela fera problème?
@Appu: gratuit (deux) code> est identique que
gratuit ("bar") code>. Ce qui peut ne pas être une catastrophe i>. Mais il est indéfini.
Puisque vous vous raccourci et renvoyez chemin1 code> ou
chemin2 code> Si l'autre paramètre est vide, il est inconnu de l'utilisateur s'il devrait libérer la valeur renvoyée ou non. Bonne prise.
J'ai mis à jour le message avec le dernier code. S'il vous plaît jetez un coup d'oeil à nouveau.
Merci d'avoir répondu. J'ai résolu le problème et j'ai appris beaucoup de choses. Merci encore.
C'est ce que j'utilise:
Juste une petite remarque afin d'améliorer votre fonction:
Windows prend en charge les deux une idée lors de la rédaction d'un projet multiplateforme pourrait être de convertir '/' code> et
'\\' code> séparateurs dans les chemins. Donc, je devrais pouvoir effectuer l'appel suivant: p>
'\\' code> à < Code> '/' code> Dans n'importe quel chemin d'entrée (à partir de l'entrée de l'utilisateur, des fichiers chargés ...), vous n'aurez donc à traiter que
'/' code> caractères. p> < p> Cordialement. P> P>
Peut-être que je suis un peu en retard à cela, mais j'ai amélioré le code mis à jour d'une manière que cela fonctionne également avec quelque chose comme ça "/../".
/* * Combine two paths into one. Note that the function * will write to the specified buffer, which has to * be allocated beforehand. * * @dst: The buffer to write to * @pth1: Part one of the path * @pth2: Part two of the path */ void joinpath(char *dst, const char *pth1, const char *pth2) { if(pth1 == NULL && pth2 == NULL) { strcpy(dst, ""); } else if(pth2 == NULL || strlen(pth2) == 0) { strcpy(dst, pth1); } else if(pth1 == NULL || strlen(pth1) == 0) { strcpy(dst, pth2); } else { char directory_separator[] = "/"; #ifdef WIN32 directory_separator[0] = '\\'; #endif const char *last_char = pth1; while(*last_char != '\0') last_char++; int append_directory_separator = 0; if(strcmp(last_char, directory_separator) != 0) { append_directory_separator = 1; } strcpy(dst, pth1); if(append_directory_separator) strcat(dst, directory_separator); strcat(dst, pth2); } char *rm, *fn; int l; while((rm = strstr (dst, "/../")) != NULL) { for(fn = (rm - 1); fn >= dst; fn--) { if(*fn == '/') { l = strlen(rm + 4); memcpy(fn + 1, rm + 4, l); *(fn + len + 1) = 0; break; } } } }
Ajouté l'extrait.