Le 14/03/09 14:57, dans , « Benoit Izac » a écrit :
if (snprintf(filename, SIZE, "%s/%s%d/%s", dirname, type, n, basename)) { Je souhaiterai me passer de SIZE et donc allouer dynamiquement filename.
Le plus simple est de demander à snprintf la taille requise avant de faire un malloc et de refaire le snprintf dans le buffer alloué :
s = snprintf(NULL, 0, "%s/%s%d/%s", dirname, type, n, basename); p = malloc(s + 1); snprintf(p, s + 1, "%s/%s%d/%s", dirname, type, n, basename);
Il faut tester les codes de retour, bien sûr; et il faut une bibliothèque C conforme.
-- Éric Lévénez FAQ de fclc : <http://www.levenez.com/lang/c/faq/>
Xavier Roche
Eric Levenez a écrit :
Le plus simple est de demander à snprintf la taille requise avant de faire un malloc et de refaire le snprintf dans le buffer alloué :
Il y a aussi une extension GNU (non POSIX) qui alloue ce qu'il faut (asprintf)
Celle-ci peut être facilement réécrite avec des fonctions POSIX en utilisant vsnprintf() et une va_list de la même manière, pour calculer la taille voulue du buffer.
Le plus simple est de demander à snprintf la taille requise avant de faire
un malloc et de refaire le snprintf dans le buffer alloué :
Il y a aussi une extension GNU (non POSIX) qui alloue ce qu'il faut
(asprintf)
Celle-ci peut être facilement réécrite avec des fonctions POSIX en
utilisant vsnprintf() et une va_list de la même manière, pour calculer
la taille voulue du buffer.
Le plus simple est de demander à snprintf la taille requise avant de faire un malloc et de refaire le snprintf dans le buffer alloué :
Il y a aussi une extension GNU (non POSIX) qui alloue ce qu'il faut (asprintf)
Celle-ci peut être facilement réécrite avec des fonctions POSIX en utilisant vsnprintf() et une va_list de la même manière, pour calculer la taille voulue du buffer.
Merci à tous les deux. Ça m'apprendra à ne pas lire la documentation dans son intégralité. De plus je viens de réaliser pourquoi gcc me renvoyait un « warning: implicit declaration of function snprintf » quand j'utilisais -ansi.
D'où ma question, comment faisait-on avant C99 (avec sprintf() donc) ?
-- Benoit Izac
Bonjour,
le 14/03/2009 à 15:09, Richard Delorme a écrit dans le message
<49bbbb68$0$17776$ba4acef3@news.orange.fr> :
Merci à tous les deux. Ça m'apprendra à ne pas lire la documentation
dans son intégralité. De plus je viens de réaliser pourquoi gcc me
renvoyait un « warning: implicit declaration of function snprintf »
quand j'utilisais -ansi.
D'où ma question, comment faisait-on avant C99 (avec sprintf() donc) ?
Merci à tous les deux. Ça m'apprendra à ne pas lire la documentation dans son intégralité. De plus je viens de réaliser pourquoi gcc me renvoyait un « warning: implicit declaration of function snprintf » quand j'utilisais -ansi.
D'où ma question, comment faisait-on avant C99 (avec sprintf() donc) ?
-- Benoit Izac
Benoit Izac
Dans le message , le 14/03/2009 à 14:57, j'ai écrit :
if (snprintf(filename, SIZE, "%s/%s%d/%s", dirname, type, n, basename)) {
Je viens de m'apercevoir que mon truc est complètement faux. Ça devrait être :
if (snprintf(filename, SIZE, "%s/%s%d/%s", dirname, type, n, basename) < SIZE) /* ok */
-- Benoit Izac
Dans le message <w53hc1w1a1y@message.id>, le 14/03/2009 à 14:57, j'ai
écrit :
if (snprintf(filename, SIZE, "%s/%s%d/%s", dirname, type, n,
basename)) {
Je viens de m'apercevoir que mon truc est complètement faux. Ça devrait
être :
if (snprintf(filename, SIZE, "%s/%s%d/%s", dirname, type, n,
basename) < SIZE)
/* ok */
D'où ma question, comment faisait-on avant C99 (avec sprintf() donc) ?
Ben on reimplementait snprintf a la main. Il y en a des paquets d'implementation dans la nature.
Il y a plusieurs choses dans la bibliotheque standard: - des trucs indispensables, impossibles a implementer de facon portable (comme malloc ou fputc). - des fonctions qui sont surtout la pour etre pratiques, et qu'on peut tres bien reimplementer soi-meme si on veut (mais souvent pas aussi efficacement que la bibliotheque du systeme, qui peut se permettre certains raccourcis pas du tout portables). snprintf en fait partie.
In article <w53d4ck18b7@message.id>, Benoit Izac <benoit.izac@free.fr> wrote:
D'où ma question, comment faisait-on avant C99 (avec sprintf() donc) ?
Ben on reimplementait snprintf a la main. Il y en a des paquets
d'implementation dans la nature.
Il y a plusieurs choses dans la bibliotheque standard:
- des trucs indispensables, impossibles a implementer de facon portable (comme
malloc ou fputc).
- des fonctions qui sont surtout la pour etre pratiques, et qu'on peut tres
bien reimplementer soi-meme si on veut (mais souvent pas aussi efficacement
que la bibliotheque du systeme, qui peut se permettre certains raccourcis pas
du tout portables). snprintf en fait partie.
D'où ma question, comment faisait-on avant C99 (avec sprintf() donc) ?
Ben on reimplementait snprintf a la main. Il y en a des paquets d'implementation dans la nature.
Il y a plusieurs choses dans la bibliotheque standard: - des trucs indispensables, impossibles a implementer de facon portable (comme malloc ou fputc). - des fonctions qui sont surtout la pour etre pratiques, et qu'on peut tres bien reimplementer soi-meme si on veut (mais souvent pas aussi efficacement que la bibliotheque du systeme, qui peut se permettre certains raccourcis pas du tout portables). snprintf en fait partie.
Xavier Roche
Benoit Izac a écrit :
D'où ma question, comment faisait-on avant C99 (avec sprintf() donc) ?
Comme on pouvait.
(1) on allouait un buffer "assez grand" (ce qui a fait les beaux jours des vulnérabilités par dépassement de tampon sur sprintf(), strcpy(), etc. -- on en voit toujours de nos jours, à ce propos :p)
(2) on allouait "proprement" en calculant la taille des arguments de type "chaine"
La solution (1) était très souvent la plus courante.
Benoit Izac a écrit :
D'où ma question, comment faisait-on avant C99 (avec sprintf() donc) ?
Comme on pouvait.
(1) on allouait un buffer "assez grand"
(ce qui a fait les beaux jours des vulnérabilités par dépassement de
tampon sur sprintf(), strcpy(), etc. -- on en voit toujours de nos
jours, à ce propos :p)
(2) on allouait "proprement" en calculant la taille des arguments de
type "chaine"
La solution (1) était très souvent la plus courante.
D'où ma question, comment faisait-on avant C99 (avec sprintf() donc) ?
Comme on pouvait.
(1) on allouait un buffer "assez grand" (ce qui a fait les beaux jours des vulnérabilités par dépassement de tampon sur sprintf(), strcpy(), etc. -- on en voit toujours de nos jours, à ce propos :p)
(2) on allouait "proprement" en calculant la taille des arguments de type "chaine"
La solution (1) était très souvent la plus courante.
Alexandre BACQUART
Benoit Izac wrote:
Bonjour,
Soit le bout de code suivant : ----------------------------------------------------------------------- #include <stdio.h>
#define SIZE 256
int main(void) { char *dirname = "/sys/class/power_supply"; char *type = "BAT"; int n = 1; char *basename = "status"; char filename[SIZE];
if (snprintf(filename, SIZE, "%s/%s%d/%s", dirname, type, n, basename)) { /* on utilise filename */ } else { /* on gere l'erreur */ }
Je souhaiterai me passer de SIZE et donc allouer dynamiquement filename.
>
J'ai pensé à faire ceci : ----------------------------------------------------------------------- char *filename; /* size_of(n) renvoie le nombre de caractère(s) nécessaire(s) pour représenter n en décimal */ size_t size = strlen(dirname) + 1 + strlen(type) + 1 + size_of(n) + 1 + strlen(basename) + 1; filename = malloc(size); if (filename) { if (snprintf(filename, size, "%s/%s%d/%s", dirname, type, n, basename)) { /* ... */ } free(filename); } -----------------------------------------------------------------------
Est-ce la seule manière de procéder ?
Il y a FILENAME_MAX dans <stdio.h>. C'est la taille maximum garantie par l'implémentation pour les noms de fichiers (la norme va à peine plus loin : s'il n'y a pratiquement aucune limite, c'est la taille *recommandée* à allouer pour contenir les noms de fichiers).
Cela me paraît donc très adapté pour allouer des chaînes dans lesquelles on va construire un chemin complet vers un fichier. Par contre, préférer un 'malloc' à une variable automatique (j'ai vu des FILENAME_MAX allant jusqu'à 4096).
Ensuite, si ton souhait est de stocker ces chemins de manière compacte, le mieux est de copier cette chaîne (que tu vas libérer de toutes façons) dans une autre, mais cette fois tu connais la taille minimum à allouer : strlen(filename)+1 (ou mieux dans ton cas, le retour de ton snprintf(...)+1).
NB: j'ai bien pensé à regarder comment asprintf (GNU_SOURCE) faisait mais j'y comprend rien. ;)
Pas standard.
-- Alex
Benoit Izac wrote:
Bonjour,
Soit le bout de code suivant :
-----------------------------------------------------------------------
#include <stdio.h>
#define SIZE 256
int main(void)
{
char *dirname = "/sys/class/power_supply";
char *type = "BAT";
int n = 1;
char *basename = "status";
char filename[SIZE];
if (snprintf(filename, SIZE, "%s/%s%d/%s", dirname, type, n,
basename)) {
/* on utilise filename */
} else {
/* on gere l'erreur */
}
Je souhaiterai me passer de SIZE et donc allouer dynamiquement filename.
>
J'ai pensé à faire ceci :
-----------------------------------------------------------------------
char *filename;
/* size_of(n) renvoie le nombre de caractère(s) nécessaire(s) pour
représenter n en décimal */
size_t size = strlen(dirname) + 1 + strlen(type) + 1 + size_of(n) + 1 +
strlen(basename) + 1;
filename = malloc(size);
if (filename) {
if (snprintf(filename, size, "%s/%s%d/%s", dirname, type, n,
basename)) {
/* ... */
}
free(filename);
}
-----------------------------------------------------------------------
Est-ce la seule manière de procéder ?
Il y a FILENAME_MAX dans <stdio.h>. C'est la taille maximum garantie par
l'implémentation pour les noms de fichiers (la norme va à peine plus
loin : s'il n'y a pratiquement aucune limite, c'est la taille
*recommandée* à allouer pour contenir les noms de fichiers).
Cela me paraît donc très adapté pour allouer des chaînes dans lesquelles
on va construire un chemin complet vers un fichier. Par contre, préférer
un 'malloc' à une variable automatique (j'ai vu des FILENAME_MAX allant
jusqu'à 4096).
Ensuite, si ton souhait est de stocker ces chemins de manière compacte,
le mieux est de copier cette chaîne (que tu vas libérer de toutes
façons) dans une autre, mais cette fois tu connais la taille minimum à
allouer : strlen(filename)+1 (ou mieux dans ton cas, le retour de ton
snprintf(...)+1).
NB: j'ai bien pensé à regarder comment asprintf (GNU_SOURCE) faisait
mais j'y comprend rien. ;)
Je souhaiterai me passer de SIZE et donc allouer dynamiquement filename.
>
J'ai pensé à faire ceci : ----------------------------------------------------------------------- char *filename; /* size_of(n) renvoie le nombre de caractère(s) nécessaire(s) pour représenter n en décimal */ size_t size = strlen(dirname) + 1 + strlen(type) + 1 + size_of(n) + 1 + strlen(basename) + 1; filename = malloc(size); if (filename) { if (snprintf(filename, size, "%s/%s%d/%s", dirname, type, n, basename)) { /* ... */ } free(filename); } -----------------------------------------------------------------------
Est-ce la seule manière de procéder ?
Il y a FILENAME_MAX dans <stdio.h>. C'est la taille maximum garantie par l'implémentation pour les noms de fichiers (la norme va à peine plus loin : s'il n'y a pratiquement aucune limite, c'est la taille *recommandée* à allouer pour contenir les noms de fichiers).
Cela me paraît donc très adapté pour allouer des chaînes dans lesquelles on va construire un chemin complet vers un fichier. Par contre, préférer un 'malloc' à une variable automatique (j'ai vu des FILENAME_MAX allant jusqu'à 4096).
Ensuite, si ton souhait est de stocker ces chemins de manière compacte, le mieux est de copier cette chaîne (que tu vas libérer de toutes façons) dans une autre, mais cette fois tu connais la taille minimum à allouer : strlen(filename)+1 (ou mieux dans ton cas, le retour de ton snprintf(...)+1).
NB: j'ai bien pensé à regarder comment asprintf (GNU_SOURCE) faisait mais j'y comprend rien. ;)
Pas standard.
-- Alex
Benoit Izac
Bonjour,
le 14/03/2009 à 19:03, Alexandre BACQUART a écrit dans le message <49bbf156$0$3094$ :
Ensuite, si ton souhait est de stocker ces chemins de manière compacte, le mieux est de copier cette chaîne (que tu vas libérer de toutes façons) dans une autre, mais cette fois tu connais la taille minimum à allouer : strlen(filename)+1 (ou mieux dans ton cas, le retour de ton snprintf(...)+1).
J'ai juste donné l'exemple que j'avais en tête. Le but était d'avoir une réponse générique qui me permette de connaître la taille exacte à allouer pour stocker cette chaîne. snprintf(NULL, 0, ...) remplit parfaitement ce rôle. Par contre, je ne comprends pas l'intérêt de la copie dans une autre chaîne.
-- Benoit Izac
Bonjour,
le 14/03/2009 à 19:03, Alexandre BACQUART a écrit dans le message
<49bbf156$0$3094$426a74cc@news.free.fr> :
Ensuite, si ton souhait est de stocker ces chemins de manière
compacte, le mieux est de copier cette chaîne (que tu vas libérer de
toutes façons) dans une autre, mais cette fois tu connais la taille
minimum à allouer : strlen(filename)+1 (ou mieux dans ton cas, le
retour de ton snprintf(...)+1).
J'ai juste donné l'exemple que j'avais en tête. Le but était d'avoir une
réponse générique qui me permette de connaître la taille exacte
à allouer pour stocker cette chaîne. snprintf(NULL, 0, ...) remplit
parfaitement ce rôle. Par contre, je ne comprends pas l'intérêt de la
copie dans une autre chaîne.
le 14/03/2009 à 19:03, Alexandre BACQUART a écrit dans le message <49bbf156$0$3094$ :
Ensuite, si ton souhait est de stocker ces chemins de manière compacte, le mieux est de copier cette chaîne (que tu vas libérer de toutes façons) dans une autre, mais cette fois tu connais la taille minimum à allouer : strlen(filename)+1 (ou mieux dans ton cas, le retour de ton snprintf(...)+1).
J'ai juste donné l'exemple que j'avais en tête. Le but était d'avoir une réponse générique qui me permette de connaître la taille exacte à allouer pour stocker cette chaîne. snprintf(NULL, 0, ...) remplit parfaitement ce rôle. Par contre, je ne comprends pas l'intérêt de la copie dans une autre chaîne.
-- Benoit Izac
Eric Levenez
Le 14/03/09 19:03, dans <49bbf156$0$3094$, « Alexandre BACQUART » a écrit :
Il y a FILENAME_MAX dans <stdio.h>. C'est la taille maximum garantie par l'implémentation pour les noms de fichiers (la norme va à peine plus loin : s'il n'y a pratiquement aucune limite, c'est la taille *recommandée* à allouer pour contenir les noms de fichiers).
Attention, FILENAME_MAX est la taille maximum d'un nom de fichier, alors que là on veut allouer le chemin complet vers ce fichier. Là la norme C ne dit rien vue que la notion de répertoire y est absente. Il y a bien PATH_MAX qui est Posix mais il est parfois faux. Le mieux est donc de ne pas supposer la taille maximale.
-- Éric Lévénez FAQ de fclc : <http://www.levenez.com/lang/c/faq/>
Le 14/03/09 19:03, dans <49bbf156$0$3094$426a74cc@news.free.fr>, « Alexandre
BACQUART » <tek512@free.DELETEME.fr> a écrit :
Il y a FILENAME_MAX dans <stdio.h>. C'est la taille maximum garantie par
l'implémentation pour les noms de fichiers (la norme va à peine plus
loin : s'il n'y a pratiquement aucune limite, c'est la taille
*recommandée* à allouer pour contenir les noms de fichiers).
Attention, FILENAME_MAX est la taille maximum d'un nom de fichier, alors que
là on veut allouer le chemin complet vers ce fichier. Là la norme C ne dit
rien vue que la notion de répertoire y est absente. Il y a bien PATH_MAX qui
est Posix mais il est parfois faux. Le mieux est donc de ne pas supposer la
taille maximale.
--
Éric Lévénez
FAQ de fclc : <http://www.levenez.com/lang/c/faq/>
Le 14/03/09 19:03, dans <49bbf156$0$3094$, « Alexandre BACQUART » a écrit :
Il y a FILENAME_MAX dans <stdio.h>. C'est la taille maximum garantie par l'implémentation pour les noms de fichiers (la norme va à peine plus loin : s'il n'y a pratiquement aucune limite, c'est la taille *recommandée* à allouer pour contenir les noms de fichiers).
Attention, FILENAME_MAX est la taille maximum d'un nom de fichier, alors que là on veut allouer le chemin complet vers ce fichier. Là la norme C ne dit rien vue que la notion de répertoire y est absente. Il y a bien PATH_MAX qui est Posix mais il est parfois faux. Le mieux est donc de ne pas supposer la taille maximale.
-- Éric Lévénez FAQ de fclc : <http://www.levenez.com/lang/c/faq/>