Concaténation

13 réponses
Avatar
Matt...
Bonjour,

soit

const char *szRepertoire =3D "/home/moi/rep";
const char *szFichier =3D "fichier";
char szChemin[REP_LEN + FIC_LEN + 1] =3D {0};

je souhaiterais concat=C3=A9ner szRepertoire et szFichier dans szChemin.=
Quel =

est la meilleur fa=C3=A7on de faire (optimis=C3=A9 temps d'ex=C3=A9cutio=
n car =C3=A9norm=C3=A9ment =

de fichier) ?

sprintf(szChemin, "%s/%s", szRepertoire, szFichier);

ou

strcpy(szChemin, szRepertoire);
strcat(szChemin, "/");
strcat(szChemin, szFichier);

Merci pour vos r=C3=A9ponses,

Matt....

-- =

Utilisant le logiciel de courrier r=C3=A9volutionnaire d'Opera : =

http://www.opera.com/mail/

10 réponses

1 2
Avatar
espie
In article , Matt... wrote:
Bonjour,

soit

const char *szRepertoire = "/home/moi/rep";
const char *szFichier = "fichier";
char szChemin[REP_LEN + FIC_LEN + 1] = {0};

je souhaiterais concaténer szRepertoire et szFichier dans szChemin. Quel
est la meilleur façon de faire (optimisé temps d'exécution car énormément
de fichier) ?

sprintf(szChemin, "%s/%s", szRepertoire, szFichier);

ou

strcpy(szChemin, szRepertoire);
strcat(szChemin, "/");
strcat(szChemin, szFichier);



Mauvaise question.

Elements de reflexion

- sprintf, strcpy, strcat font partie de la bibliotheque standard, donc
sont connus du compilo... ce qui veut dire que celui-ci a le droit (confere
la norme) d'optimiser les utilisations de ces fonctions de maniere violente,
y compris en les virant et en remplacant par ses propres boucles.
Vu que tes deux constructions font la meme chose, globalement, ben le compilo
peut s'en rendre compte et optimiser. La seule vraie facon de voir si c'est
le cas, c'est de regarder le code genere, ou de chronometrer le resultat.

- si on parle de timing, il manque les vrais elements de reflexion. Tu dis
"beaucoup de fichiers", mais ca ne dit rien. On ne sait pas comment ca
s'organise en terme de boucles et de stockage. Typiquement, est-ce que tu
veux fabriquer TOUS les szChemin pour plus tard, ou est-ce que tu veux
en fabriquer un a la volee pour faire d'autres trucs avec lui ?

- si tu veux fabriquer tous les szChemin pour plus tard, il y a de fortes
chances que le temps d'execution de ces fonctions n'aient qu'une incidence
minime sur la vitesse de ton code, qui sera domine par le temps necessaire
pour ecrire plein plein plein de donnees.

- si tu veux fabriquer les szChemin a la volee, est-ce que les repertoires
sont repartis n'importe comment, ou est-ce que tu as plein de fichiers
d'affilee dans le meme repertoire, auquel cas ca vaut le coup de ne pas
refaire les calculs plusieurs fois.

Bref, tu nous fais de la micro-optimisation prematuree. Ton probleme n'est
pas bien pose, la vraie solution est sans doute avant.

Personnellement, je n'utiliserai pas sprintf, vu que snprintf est standard...
Ca m'evitera des jolies gauffres si je me trompe dans ma taille. Cote
lisibilite, je prefere largement
snprintf(fullname, sizeof fullname, "%s/%s", dir, file);
(faut arreter la notation prefixe polonaise, qui est juste moche, illisible
et n'apporte rien).

C'est pas forcement tres efficace, mais c'est pas forcement important. Et
si ca ne va pas assez vite, je vais commencer par sortir mon profiler, et
trouver les vrais endroits ou optimiser...
Avatar
Cyprien Nicolas
Salut,

Le 23/06/2013 09:17, Matt... écrivit :
const char *szRepertoire = "/home/moi/rep";
const char *szFichier = "fichier";
char szChemin[REP_LEN + FIC_LEN + 1] = {0};



Il manque pas +1 pour le séparateur en plus du ?

je souhaiterais concaténer szRepertoire et szFichier dans szChemin.
Quel est la meilleur façon de faire (optimisé temps d'exécution car
énormément de fichier) ?



Je dirais: Fait des testes/benches, ça peut dépendre de la libc sur
laquelle ton programme s'exécute, de l'architecture, de la version de
GCC utilisée pour compiler le code, etc.

sprintf(szChemin, "%s/%s", szRepertoire, szFichier);

ou

strcpy(szChemin, szRepertoire);
strcat(szChemin, "/");
strcat(szChemin, szFichier);



Sur un plan plus lisibilité du code (subjectif), je préfère la première.

--
« Ceci n'est pas une signature. » — René Magritte (Apocryphe)
Avatar
Matt...
Salut,

Le Sun, 23 Jun 2013 10:38:33 +0200, Cyprien Nicolas >
a écrit:

Salut,

Le 23/06/2013 09:17, Matt... écrivit :
const char *szRepertoire = "/home/moi/rep";
const char *szFichier = "fichier";
char szChemin[REP_LEN + FIC_LEN + 1] = {0};



Il manque pas +1 pour le séparateur en plus du ?



C'est pas faux...


je souhaiterais concaténer szRepertoire et szFichier dans szChem in.
Quel est la meilleur façon de faire (optimisé temps d'exà ©cution car
énormément de fichier) ?



Je dirais: Fait des testes/benches, ça peut dépendre de la l ibc sur
laquelle ton programme s'exécute, de l'architecture, de la versio n de
GCC utilisée pour compiler le code, etc.




Je vais donc faire des testes sur une boucle pour voir l'efficacité .

sprintf(szChemin, "%s/%s", szRepertoire, szFichier);

ou

strcpy(szChemin, szRepertoire);
strcat(szChemin, "/");
strcat(szChemin, szFichier);



Sur un plan plus lisibilité du code (subjectif), je préfè re la première.




Merci,

Matt...


--
Utilisant le logiciel de courrier révolutionnaire d'Opera :
http://www.opera.com/mail/
Avatar
Olivier Miakinen
Le 23/06/2013 10:13, Marc Espie répondait à Matt... :

Personnellement, je n'utiliserai pas sprintf, vu que snprintf est standard...
Ca m'evitera des jolies gauffres si je me trompe dans ma taille. Cote
lisibilite, je prefere largement
snprintf(fullname, sizeof fullname, "%s/%s", dir, file);



Oui, exactement.

(faut arreter la notation prefixe polonaise, qui est juste moche, illisible
et n'apporte rien).



La notation hongroise, tu veux dire ? Si oui, je suis entièrement
d'accord aussi.
Avatar
Matt...
Le Sun, 23 Jun 2013 10:13:01 +0200, Marc Espie a é crit:

In article , Matt...
wrote:
Bonjour,

soit

const char *szRepertoire = "/home/moi/rep";
const char *szFichier = "fichier";
char szChemin[REP_LEN + FIC_LEN + 1] = {0};

je souhaiterais concaténer szRepertoire et szFichier dans szChemin.
Quel
est la meilleur façon de faire (optimisé temps d'exécution car
énormément
de fichier) ?

sprintf(szChemin, "%s/%s", szRepertoire, szFichier);

ou

strcpy(szChemin, szRepertoire);
strcat(szChemin, "/");
strcat(szChemin, szFichier);



Mauvaise question.

Elements de reflexion

- sprintf, strcpy, strcat font partie de la bibliotheque standard, don c
sont connus du compilo... ce qui veut dire que celui-ci a le droit
(confere
la norme) d'optimiser les utilisations de ces fonctions de maniere
violente,
y compris en les virant et en remplacant par ses propres boucles.
Vu que tes deux constructions font la meme chose, globalement, ben le
compilo
peut s'en rendre compte et optimiser. La seule vraie facon de voir si
c'est
le cas, c'est de regarder le code genere, ou de chronometrer le result at.

- si on parle de timing, il manque les vrais elements de reflexion. Tu
dis
"beaucoup de fichiers", mais ca ne dit rien. On ne sait pas comment ca
s'organise en terme de boucles et de stockage. Typiquement, est-ce que tu
veux fabriquer TOUS les szChemin pour plus tard, ou est-ce que tu veux
en fabriquer un a la volee pour faire d'autres trucs avec lui ?

- si tu veux fabriquer tous les szChemin pour plus tard, il y a de for tes
chances que le temps d'execution de ces fonctions n'aient qu'une
incidence
minime sur la vitesse de ton code, qui sera domine par le temps
necessaire
pour ecrire plein plein plein de donnees.

- si tu veux fabriquer les szChemin a la volee, est-ce que les
repertoires
sont repartis n'importe comment, ou est-ce que tu as plein de fichiers
d'affilee dans le meme repertoire, auquel cas ca vaut le coup de ne pa s
refaire les calculs plusieurs fois.

Bref, tu nous fais de la micro-optimisation prematuree. Ton probleme
n'est
pas bien pose, la vraie solution est sans doute avant.

Personnellement, je n'utiliserai pas sprintf, vu que snprintf est
standard...
Ca m'evitera des jolies gauffres si je me trompe dans ma taille. Cote
lisibilite, je prefere largement
snprintf(fullname, sizeof fullname, "%s/%s", dir, file);
(faut arreter la notation prefixe polonaise, qui est juste moche,
illisible
et n'apporte rien).

C'est pas forcement tres efficace, mais c'est pas forcement important. Et
si ca ne va pas assez vite, je vais commencer par sortir mon profiler, et
trouver les vrais endroits ou optimiser...



Merci pour ta réponse,

En fait, c'est pour copier les fichiers d'un répertoire à un a utre.
Je parcours le répertoire A, je récupère le nom du premie r fichier, je le
concatène au répertoire B et je copie et ainsi de suite. Donc les chemins
pour les fichiers à copier et copiés sont différents pour chaque itération.

Je vais donc faire des testes avec les deux méthodes.

Question subsidiaire : Pour copier un fichier, j'utilise la libgio
(g_file_copy ()). Est ce un bon choix ?

Matt...



--
Utilisant le logiciel de courrier révolutionnaire d'Opera :
http://www.opera.com/mail/
Avatar
Matt...
Le Sun, 23 Jun 2013 11:11:46 +0200, Olivier Miakinen
<om+ a écrit:

Le 23/06/2013 10:13, Marc Espie répondait à Matt... :

Personnellement, je n'utiliserai pas sprintf, vu que snprintf est
standard...
Ca m'evitera des jolies gauffres si je me trompe dans ma taille. Cote
lisibilite, je prefere largement
snprintf(fullname, sizeof fullname, "%s/%s", dir, file);



Oui, exactement.




J'en prends note.

(faut arreter la notation prefixe polonaise, qui est juste moche,
illisible
et n'apporte rien).



La notation hongroise, tu veux dire ? Si oui, je suis entièrement
d'accord aussi.




Question de goût, j'aime bien.

Matt...

--
Utilisant le logiciel de courrier révolutionnaire d'Opera :
http://www.opera.com/mail/
Avatar
Olivier Miakinen
Le 23/06/2013 11:13, Matt... répondait à Marc Espie :
Le Sun, 23 Jun 2013 10:13:01 +0200, Marc Espie a écrit:

[citation intégrale]



Merci pour ta réponse,

[...]



Euh... quand tu ne réponds pas à un point en particulier, merci
d'alléger la réponse en ne citant pas tout !
Avatar
espie
In article , Matt... wrote:
En fait, c'est pour copier les fichiers d'un répertoire à un autre.
Je parcours le répertoire A, je récupère le nom du premier fichier, je le
concatène au répertoire B et je copie et ainsi de suite. Donc les chemins
pour les fichiers à copier et copiés sont différents pour chaque itération.



Donc du coup, les noms de repertoire sont constants, et c'est donc un peu
idiot de tout reconstruire a chaque fois... tu as fortement interet
a initialiser tes chaines avec le nom du repertoire, et a rajouter le nom
du fichier au bon endroit, si ca pose des problemes de performance.

Mais bon, du coup, ca n'a aucune espece d'importance, en realite, parce
que c'est la copie qui va prendre du temps! donc fais au plus simple et
propre.


Je vais donc faire des testes avec les deux méthodes.

Question subsidiaire : Pour copier un fichier, j'utilise la libgio
(g_file_copy ()). Est ce un bon choix ?



Si je met ma casquette de developpeur BSD: non, c'est un mauvais choix,
puisque c'est du logiciel GPL. :)
(et techniquement, je deteste tout ce qui est glib/gio, parce que c'est
de la reinvention cradouille moche d'oriente-objet mal foutu et hyper
verbeux en C, avec une boucle d'evenement incomprehensible et qui laggue
generalement pour des raisons surprenantes... on sait que les gars qui ont
pondu glib et gtk+ n'aiment pas C++. On peut aussi deduire de leur code
qu'ils n'y ont vraiment rien compris, j'ai rarement vu une aussi belle
collection de reinvention de roues carrees qu'en lisant ce code-la)

Bon, dans l'absolu, ca doit pas faire de grosses differences de perf
avec faire les choses a la main a l'ancienne, mais la-aussi, la meilleure
facon de le savoir c'est de mesurer !
Avatar
Cyprien Nicolas
Le 23/06/2013 11:13, Matt... écrivit :
Question subsidiaire : Pour copier un fichier, j'utilise la libgio
(g_file_copy ()). Est ce un bon choix ?



Oui et Non.

Soit tu utilises les abstractions de la Glib, et tu fais tout avec, soit
rien. Mais mélanger les deux est risque de problème (notamment avec les
histoires de g_free/g_object_unref à faire un coup oui ou un coup non).
g_file_copy travaille sur des GFile* dont il faut gérer la durée de vie.

Si tu fais tout en C "brut", autant utiliser fread/fwrite.

Utiliser la Glib fournit une abstraction intéressant pour ne pas gérer
les histoires de noms de fichiers en utf-8 par exemple, ou de la
portabilité entre différents systèmes qui ont la Glib (dont Windows). Il
y a aussi des GDir, des g_file_[gs]et_contents, etc…

--
« Ceci n'est pas une signature. » — René Magritte (Apocryphe)
Avatar
Matt...
Le Sun, 23 Jun 2013 10:13:01 +0200, Marc Espie a é crit:

In article , Matt...
wrote:
Bonjour,

soit

const char *szRepertoire = "/home/moi/rep";
const char *szFichier = "fichier";
char szChemin[REP_LEN + FIC_LEN + 1] = {0};

je souhaiterais concaténer szRepertoire et szFichier dans szChemin.
Quel
est la meilleur façon de faire (optimisé temps d'exécution car
énormément
de fichier) ?

sprintf(szChemin, "%s/%s", szRepertoire, szFichier);

ou

strcpy(szChemin, szRepertoire);
strcat(szChemin, "/");
strcat(szChemin, szFichier);



Mauvaise question.

Elements de reflexion

- sprintf, strcpy, strcat font partie de la bibliotheque standard, don c
sont connus du compilo... ce qui veut dire que celui-ci a le droit
(confere
la norme) d'optimiser les utilisations de ces fonctions de maniere
violente,
y compris en les virant et en remplacant par ses propres boucles.
Vu que tes deux constructions font la meme chose, globalement, ben le
compilo
peut s'en rendre compte et optimiser. La seule vraie facon de voir si
c'est
le cas, c'est de regarder le code genere, ou de chronometrer le result at.




J'ai fait quelques testes et la deuxième méthode s'avère plus rapide.

Personnellement, je n'utiliserai pas sprintf, vu que snprintf est
standard...
Ca m'evitera des jolies gauffres si je me trompe dans ma taille.





Effectivement.

Merci pour ta réponse,

Matt...

--
Utilisant le logiciel de courrier révolutionnaire d'Opera :
http://www.opera.com/mail/
1 2