J'ai écrit une fonction qui remplace la virgule par un point dans une chaine de caractères pour ensuite permettre de faire un
calcul.
Pour copier une chaine dans une autre chaine, j'utilise memcpy.
Est ce nécessaire d'écrire
memcpy(ch, c, sizeof(char) * taille);
ou bien je peux me contenter d'écrire
memcpy(ch, c, taille);
Toutes critiques sur la fonction seront les bienvenues.
Merci.
Alain CROS
#include <string.h>
int convstrnum(int taille, char *c)
/* Remplace, dans une chaine de caractères représentant un chiffre,
la virgule par un point.
Retourne :
la position de ce point dans la chaine (base 1).
0 si pas de point.
-1 si pas un chiffre (la chaine reste inchangée).
*/
{
int i = 1, j = 0, k = 0;
char ch[taille + 1];
char *pch = ch;
memcpy(ch, c, sizeof(char) * taille);
ch[taille] = '\0';
while(*pch != '\0')
{
if((*pch < '0') || (*pch > '9'))
switch(*pch)
{
case '.':
j = (++k == 2) ? -1 : j;
break;
case ',':
*pch-- = '.';
j = i--;
break;
default:
j = -1;
}
if(j == -1)
break;
*pch++;
i++;
}
if(j != -1)
memcpy(c, ch, sizeof(char) * taille);
return(j);
}
Merci pour les nombreuses réponses. J'analyse tous ça pour essayer d'en tirer de bonnes pratiques.
Alain CROS
Regarde aussi cette version :
#include <string.h> #include <ctype.h>
#define INVALID_STRING -1 int str_to_numstr( int taille, char * str ) { int i ; char * pStr = str ; int point_posit = 0 ; int rc = 0 ;
for( i = 0 ; i++ < taille ; pStr++ ) { int c = * pStr ; if ( ! isdigit( c ) ) { if ( c == ',' ) { // on retourne INVALID STRING s'il y a plusieurs ',' if ( point_posit ) { return( INVALID_STRING ) ; } point_posit = i ; } else { return( INVALID_STRING ) ; } } } if ( point_posit ) { *( str + point_posit - 1 ) = '.' ; rc = point_posit ; } return( rc ) ; }
Harpo
Emmanuel Delahaye wrote:
char ch[taille + 1];
[C99] VLA ? Je ne connais pas d'implémentation conforme. Qu'est-ce qui ne va pas avec malloc() ?
Ca coûte cher.
On peut essayer alloca( ) en deçà d'une certaine taille en testant si le système le permet, je ne vois sinon aucune raison particulière de ne pas allouer dans la pile.
Emmanuel Delahaye wrote:
char ch[taille + 1];
[C99] VLA ? Je ne connais pas d'implémentation conforme. Qu'est-ce qui
ne va pas avec malloc() ?
Ca coûte cher.
On peut essayer alloca( ) en deçà d'une certaine taille en testant si le
système le permet, je ne vois sinon aucune raison particulière de ne
pas allouer dans la pile.
[C99] VLA ? Je ne connais pas d'implémentation conforme. Qu'est-ce qui ne va pas avec malloc() ?
Ca coûte cher.
On peut essayer alloca( ) en deçà d'une certaine taille en testant si le système le permet, je ne vois sinon aucune raison particulière de ne pas allouer dans la pile.
Emmanuel Delahaye
Harpo wrote on 23/09/05 :
Emmanuel Delahaye wrote:
char ch[taille + 1];
[C99] VLA ? Je ne connais pas d'implémentation conforme. Qu'est-ce qui ne va pas avec malloc() ?
Ca coûte cher.
En terme de quoi ? Temps d'exécution, taille, mémoire ?
On peut essayer alloca( ) en deçà d'une certaine taille en testant si le système le permet,
Comment on teste ?
je ne vois sinon aucune raison particulière de ne pas allouer dans la pile.
VLA : Un crash est possible (débordement de pile). En cas d'echec d'allocation, il n'y a pas de contrôle possible. On travaille sans filet.
Quand à alloca(), c'est une extension, et si j'ai bien suivi, elle est obsolète, déconseillée, et il est suggéré de la remplacer par malloc().
-- Emmanuel The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html The C-library: http://www.dinkumware.com/refxc.html
.sig under repair
Harpo wrote on 23/09/05 :
Emmanuel Delahaye wrote:
char ch[taille + 1];
[C99] VLA ? Je ne connais pas d'implémentation conforme. Qu'est-ce qui
ne va pas avec malloc() ?
Ca coûte cher.
En terme de quoi ? Temps d'exécution, taille, mémoire ?
On peut essayer alloca( ) en deçà d'une certaine taille en testant si le
système le permet,
Comment on teste ?
je ne vois sinon aucune raison particulière de ne
pas allouer dans la pile.
VLA : Un crash est possible (débordement de pile). En cas d'echec
d'allocation, il n'y a pas de contrôle possible. On travaille sans
filet.
Quand à alloca(), c'est une extension, et si j'ai bien suivi, elle est
obsolète, déconseillée, et il est suggéré de la remplacer par malloc().
--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html
[C99] VLA ? Je ne connais pas d'implémentation conforme. Qu'est-ce qui ne va pas avec malloc() ?
Ca coûte cher.
En terme de quoi ? Temps d'exécution, taille, mémoire ?
On peut essayer alloca( ) en deçà d'une certaine taille en testant si le système le permet,
Comment on teste ?
je ne vois sinon aucune raison particulière de ne pas allouer dans la pile.
VLA : Un crash est possible (débordement de pile). En cas d'echec d'allocation, il n'y a pas de contrôle possible. On travaille sans filet.
Quand à alloca(), c'est une extension, et si j'ai bien suivi, elle est obsolète, déconseillée, et il est suggéré de la remplacer par malloc().
-- Emmanuel The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html The C-library: http://www.dinkumware.com/refxc.html
.sig under repair
Harpo
Emmanuel Delahaye wrote:
ne va pas avec malloc() ?
Ca coûte cher.
En terme de quoi ? Temps d'exécution, taille, mémoire ?
principalement temps et sans doute plus de possibilités d'interruption pour page fault.
On peut essayer alloca( ) en deçà d'une certaine taille en testant si le système le permet,
Comment on teste ?
Pendant la phase d'installation d'un logiciel on teste généralement les fonctions souhaitées disponibles et on crée un fichier, disons 'config.h' dans lequel on place des choses comme : #define HAVE_ALLOCA
que l'on peut ensuite tester dans un programme. #ifdef HAVE_ALLOCA
je ne vois sinon aucune raison particulière de ne pas allouer dans la pile.
VLA : Un crash est possible (débordement de pile). En cas d'echec d'allocation, il n'y a pas de contrôle possible. On travaille sans filet.
Mon conseil dans ce cas, n'appelez jamais de fonctions et n'utilisez jamais de variables automatiques. Passer un argument à main( ) est déjà risqué. Commencez tous les programmes par ce test : if ( argc > 1 ) abort ; Si vous arrivez jusque là, cela vous évitera de vous planter après.
Quand à alloca(), c'est une extension, et si j'ai bien suivi, elle est obsolète, déconseillée, et il est suggéré de la remplacer par malloc().
Personne ne m'a demandé mon avis.
Emmanuel Delahaye wrote:
ne va pas avec malloc() ?
Ca coûte cher.
En terme de quoi ? Temps d'exécution, taille, mémoire ?
principalement temps et sans doute plus de possibilités d'interruption
pour page fault.
On peut essayer alloca( ) en deçà d'une certaine taille en testant si
le système le permet,
Comment on teste ?
Pendant la phase d'installation d'un logiciel on teste généralement les
fonctions souhaitées disponibles et on crée un fichier, disons
'config.h' dans lequel on place des choses comme :
#define HAVE_ALLOCA
que l'on peut ensuite tester dans un programme.
#ifdef HAVE_ALLOCA
je ne vois sinon aucune raison particulière de ne
pas allouer dans la pile.
VLA : Un crash est possible (débordement de pile). En cas d'echec
d'allocation, il n'y a pas de contrôle possible. On travaille sans
filet.
Mon conseil dans ce cas, n'appelez jamais de fonctions et n'utilisez
jamais de variables automatiques.
Passer un argument à main( ) est déjà risqué.
Commencez tous les programmes par ce test :
if ( argc > 1 ) abort ;
Si vous arrivez jusque là, cela vous évitera de vous planter après.
Quand à alloca(), c'est une extension, et si j'ai bien suivi, elle est
obsolète, déconseillée, et il est suggéré de la remplacer par
malloc().
En terme de quoi ? Temps d'exécution, taille, mémoire ?
principalement temps et sans doute plus de possibilités d'interruption pour page fault.
On peut essayer alloca( ) en deçà d'une certaine taille en testant si le système le permet,
Comment on teste ?
Pendant la phase d'installation d'un logiciel on teste généralement les fonctions souhaitées disponibles et on crée un fichier, disons 'config.h' dans lequel on place des choses comme : #define HAVE_ALLOCA
que l'on peut ensuite tester dans un programme. #ifdef HAVE_ALLOCA
je ne vois sinon aucune raison particulière de ne pas allouer dans la pile.
VLA : Un crash est possible (débordement de pile). En cas d'echec d'allocation, il n'y a pas de contrôle possible. On travaille sans filet.
Mon conseil dans ce cas, n'appelez jamais de fonctions et n'utilisez jamais de variables automatiques. Passer un argument à main( ) est déjà risqué. Commencez tous les programmes par ce test : if ( argc > 1 ) abort ; Si vous arrivez jusque là, cela vous évitera de vous planter après.
Quand à alloca(), c'est une extension, et si j'ai bien suivi, elle est obsolète, déconseillée, et il est suggéré de la remplacer par malloc().
Personne ne m'a demandé mon avis.
Harpo
Emmanuel Delahaye wrote:
La chaine initiale est donc modifiable. Je recommande size_t pour la taille.
Vous avez raison, mais peut-être vaut-il mieux ne pas le surcharger de considérations secondaires.
Si 'c' est l'adresse d'une chaine conforme, à quoi sert la taille ?
J'aurais plutôt tendance à penser : si on a la taille, à quoi sert de se préoccuper du 0 terminal.
Ca me parait hyper compliqué! Si la chaine initiale est modifiable, il suffit de la modifier directement.
Je suis tout à fait d'accord sur ce point.
Emmanuel Delahaye wrote:
La chaine initiale est donc modifiable. Je recommande size_t pour la
taille.
Vous avez raison, mais peut-être vaut-il mieux ne pas le surcharger de
considérations secondaires.
Si 'c' est l'adresse d'une chaine conforme, à quoi sert la
taille ?
J'aurais plutôt tendance à penser : si on a la taille, à quoi sert de se
préoccuper du 0 terminal.
Ca me parait hyper compliqué! Si la chaine initiale est modifiable, il
suffit de la modifier directement.
int isCharValid(char c) { return ( (isdigit(c) || c == '.' || c == ',') ? 1 : 0 );
COmpliqué...
oui...
return (isdigit(c) || c == '.' || c == ',');
}
/** * comma2dot * Remplace la virgule par le point comme séparateur dans une chaine numérique * @param[in] s chaine à traiter * @return rc * 0 : succes * -1 : argument nul * -2 : pb allocation * -3 : chaine fournie non valide */ int comma2dot(char * s) { int rc = 0;
int isCharValid(char c)
{
return ( (isdigit(c) || c == '.' || c == ',') ? 1 : 0 );
COmpliqué...
oui...
return (isdigit(c) || c == '.' || c == ',');
}
/**
* comma2dot
* Remplace la virgule par le point comme séparateur dans une chaine
numérique
* @param[in] s chaine à traiter
* @return rc
* 0 : succes
* -1 : argument nul
* -2 : pb allocation
* -3 : chaine fournie non valide
*/
int comma2dot(char * s)
{
int rc = 0;
int isCharValid(char c) { return ( (isdigit(c) || c == '.' || c == ',') ? 1 : 0 );
COmpliqué...
oui...
return (isdigit(c) || c == '.' || c == ',');
}
/** * comma2dot * Remplace la virgule par le point comme séparateur dans une chaine numérique * @param[in] s chaine à traiter * @return rc * 0 : succes * -1 : argument nul * -2 : pb allocation * -3 : chaine fournie non valide */ int comma2dot(char * s) { int rc = 0;
if (s != NULL) {
size_t lg = strlen(s); char * tmp = malloc(lg+1);
Ca fout la trouille!
Quoi ça ? Le fait d'utiliser un malloc ?
A+ Regis
Charlie Gordon
"Harpo" wrote in message news:433448b6$0$17240$
Emmanuel Delahaye wrote:
ne va pas avec malloc() ?
Ca coûte cher.
En terme de quoi ? Temps d'exécution, taille, mémoire ? principalement temps et sans doute plus de possibilités d'interruption
pour page fault.
C'est surtout totalement inutile dans le contexte de l'OP. Comme tout le monde l'a remarqué.
...
Mon conseil dans ce cas, n'appelez jamais de fonctions et n'utilisez jamais de variables automatiques. Passer un argument à main( ) est déjà risqué. Commencez tous les programmes par ce test : if ( argc > 1 ) abort ; Si vous arrivez jusque là, cela vous évitera de vous planter après.
En fait cette instruction a peu de chances d'avoir le moindre effet ;-)
-- Chqrlie. (back from the underworld)
"Harpo" <trashcan@hotmail.com> wrote in message
news:433448b6$0$17240$8fcfb975@news.wanadoo.fr...
Emmanuel Delahaye wrote:
ne va pas avec malloc() ?
Ca coûte cher.
En terme de quoi ? Temps d'exécution, taille, mémoire ?
principalement temps et sans doute plus de possibilités d'interruption
pour page fault.
C'est surtout totalement inutile dans le contexte de l'OP. Comme tout le monde
l'a remarqué.
...
Mon conseil dans ce cas, n'appelez jamais de fonctions et n'utilisez
jamais de variables automatiques.
Passer un argument à main( ) est déjà risqué.
Commencez tous les programmes par ce test :
if ( argc > 1 ) abort ;
Si vous arrivez jusque là, cela vous évitera de vous planter après.
En fait cette instruction a peu de chances d'avoir le moindre effet ;-)
En terme de quoi ? Temps d'exécution, taille, mémoire ? principalement temps et sans doute plus de possibilités d'interruption
pour page fault.
C'est surtout totalement inutile dans le contexte de l'OP. Comme tout le monde l'a remarqué.
...
Mon conseil dans ce cas, n'appelez jamais de fonctions et n'utilisez jamais de variables automatiques. Passer un argument à main( ) est déjà risqué. Commencez tous les programmes par ce test : if ( argc > 1 ) abort ; Si vous arrivez jusque là, cela vous évitera de vous planter après.
En fait cette instruction a peu de chances d'avoir le moindre effet ;-)
-- Chqrlie. (back from the underworld)
Alcor
Pour copier une chaine dans une autre chaine, j'utilise memcpy.
ben normalement, c'est strcpy.
memcpy, c'est pour un buffer de longeur fixe...
Est ce nécessaire d'écrire memcpy(ch, c, sizeof(char) * taille); ou bien je peux me contenter d'écrire memcpy(ch, c, taille);
ben la taille du type char n'a pas trop changé ces trente dernières années, je pense qu'on peut se contenter de la deuxième version. à moins que tu n'envisages de faire une version unicode...
Toutes critiques sur la fonction seront les bienvenues.
Merci.
Alain CROS
#include <string.h>
int convstrnum(int taille, char *c) /* Remplace, dans une chaine de caractères représentant un chiffre, la virgule par un point. Retourne : la position de ce point dans la chaine (base 1). 0 si pas de point. -1 si pas un chiffre (la chaine reste inchangée). */ { int i = 1, j = 0, k = 0; char ch[taille + 1]; char *pch = ch; memcpy(ch, c, sizeof(char) * taille); ch[taille] = ' '; while(*pch != ' ') { if((*pch < '0') || (*pch > '9')) switch(*pch) { case '.': j = (++k == 2) ? -1 : j; break; case ',': *pch-- = '.'; j = i--; break; default: j = -1; } if(j == -1) break; *pch++; i++; } if(j != -1) memcpy(c, ch, sizeof(char) * taille); return(j); }
ben si tu n'as pas besoin de super performances, je suppose que ça va marcher.
sinon les noms de variable sur une lettre c'était bon dans les années 80, depuis on a découvert que c'était super chiant à relire on mettra plutot des InputString CurrentLocation ReturnCode à la place.
de plus en C, on a l'habitude de raisoner en base 0. tu viens du basic ?
mais l'intention est bonne. je pense que dans 6 mois à deux ans tu revisitera cette fonction et qu'elle tiendra sur 3 lignes...
par exemple, as-tu vraiement besoin d'un code de retour si détaillé ? ton programme principal exploite-t-il vraiment toutes les nuances?
_______________________________________________________________________________ Posted Via Uncensored-News.Com - Accounts Starting At $6.95 - http://www.uncensored-news.com <><><><><><><> The Worlds Uncensored News Source <><><><><><><><>
Pour copier une chaine dans une autre chaine, j'utilise memcpy.
ben normalement, c'est strcpy.
memcpy, c'est pour un buffer de longeur fixe...
Est ce nécessaire d'écrire
memcpy(ch, c, sizeof(char) * taille);
ou bien je peux me contenter d'écrire
memcpy(ch, c, taille);
ben la taille du type char n'a pas trop changé ces trente dernières années,
je pense qu'on peut se contenter de la deuxième version. à moins que tu
n'envisages de faire une version unicode...
Toutes critiques sur la fonction seront les bienvenues.
Merci.
Alain CROS
#include <string.h>
int convstrnum(int taille, char *c)
/* Remplace, dans une chaine de caractères représentant un chiffre,
la virgule par un point.
Retourne :
la position de ce point dans la chaine (base 1).
0 si pas de point.
-1 si pas un chiffre (la chaine reste inchangée).
*/
{
int i = 1, j = 0, k = 0;
char ch[taille + 1];
char *pch = ch;
memcpy(ch, c, sizeof(char) * taille);
ch[taille] = ' ';
while(*pch != ' ')
{
if((*pch < '0') || (*pch > '9'))
switch(*pch)
{
case '.':
j = (++k == 2) ? -1 : j;
break;
case ',':
*pch-- = '.';
j = i--;
break;
default:
j = -1;
}
if(j == -1)
break;
*pch++;
i++;
}
if(j != -1)
memcpy(c, ch, sizeof(char) * taille);
return(j);
}
ben si tu n'as pas besoin de super performances, je suppose que ça va
marcher.
sinon les noms de variable sur une lettre c'était bon dans les années 80,
depuis on a découvert que c'était super chiant à relire on mettra plutot
des
InputString
CurrentLocation
ReturnCode
à la place.
de plus en C, on a l'habitude de raisoner en base 0. tu viens du basic ?
mais l'intention est bonne. je pense que dans 6 mois à deux ans tu
revisitera cette fonction et qu'elle tiendra sur 3 lignes...
par exemple, as-tu vraiement besoin d'un code de retour si détaillé ? ton
programme principal exploite-t-il vraiment toutes les nuances?
_______________________________________________________________________________
Posted Via Uncensored-News.Com - Accounts Starting At $6.95 - http://www.uncensored-news.com
<><><><><><><> The Worlds Uncensored News Source <><><><><><><><>
Pour copier une chaine dans une autre chaine, j'utilise memcpy.
ben normalement, c'est strcpy.
memcpy, c'est pour un buffer de longeur fixe...
Est ce nécessaire d'écrire memcpy(ch, c, sizeof(char) * taille); ou bien je peux me contenter d'écrire memcpy(ch, c, taille);
ben la taille du type char n'a pas trop changé ces trente dernières années, je pense qu'on peut se contenter de la deuxième version. à moins que tu n'envisages de faire une version unicode...
Toutes critiques sur la fonction seront les bienvenues.
Merci.
Alain CROS
#include <string.h>
int convstrnum(int taille, char *c) /* Remplace, dans une chaine de caractères représentant un chiffre, la virgule par un point. Retourne : la position de ce point dans la chaine (base 1). 0 si pas de point. -1 si pas un chiffre (la chaine reste inchangée). */ { int i = 1, j = 0, k = 0; char ch[taille + 1]; char *pch = ch; memcpy(ch, c, sizeof(char) * taille); ch[taille] = ' '; while(*pch != ' ') { if((*pch < '0') || (*pch > '9')) switch(*pch) { case '.': j = (++k == 2) ? -1 : j; break; case ',': *pch-- = '.'; j = i--; break; default: j = -1; } if(j == -1) break; *pch++; i++; } if(j != -1) memcpy(c, ch, sizeof(char) * taille); return(j); }
ben si tu n'as pas besoin de super performances, je suppose que ça va marcher.
sinon les noms de variable sur une lettre c'était bon dans les années 80, depuis on a découvert que c'était super chiant à relire on mettra plutot des InputString CurrentLocation ReturnCode à la place.
de plus en C, on a l'habitude de raisoner en base 0. tu viens du basic ?
mais l'intention est bonne. je pense que dans 6 mois à deux ans tu revisitera cette fonction et qu'elle tiendra sur 3 lignes...
par exemple, as-tu vraiement besoin d'un code de retour si détaillé ? ton programme principal exploite-t-il vraiment toutes les nuances?
_______________________________________________________________________________ Posted Via Uncensored-News.Com - Accounts Starting At $6.95 - http://www.uncensored-news.com <><><><><><><> The Worlds Uncensored News Source <><><><><><><><>
Harpo
Charlie Gordon wrote:
Commencez tous les programmes par ce test : if ( argc > 1 ) abort ; Si vous arrivez jusque là, cela vous évitera de vous planter après.
En fait cette instruction a peu de chances d'avoir le moindre effet ;-)
Ne pas dépasser le stade de la compil évite des ennuis par la suite.
Charlie Gordon wrote:
Commencez tous les programmes par ce test :
if ( argc > 1 ) abort ;
Si vous arrivez jusque là, cela vous évitera de vous planter après.
En fait cette instruction a peu de chances d'avoir le moindre effet
;-)
Ne pas dépasser le stade de la compil évite des ennuis par la suite.
Commencez tous les programmes par ce test : if ( argc > 1 ) abort ; Si vous arrivez jusque là, cela vous évitera de vous planter après.
En fait cette instruction a peu de chances d'avoir le moindre effet ;-)
Ne pas dépasser le stade de la compil évite des ennuis par la suite.
Harpo
Alcor wrote:
Pour copier une chaine dans une autre chaine, j'utilise memcpy.
ben normalement, c'est strcpy.
Lorsque l'on connaît la longueur de la chaine, je pense qu'il est préférable d'utiliser memcpy( ), a priori bien plus rapide, surtout pour des longues chaînes. Mais dans le cas présent, ni l'un ni l'autre ne servait.
Alcor wrote:
Pour copier une chaine dans une autre chaine, j'utilise memcpy.
ben normalement, c'est strcpy.
Lorsque l'on connaît la longueur de la chaine, je pense qu'il est
préférable d'utiliser memcpy( ), a priori bien plus rapide, surtout
pour des longues chaînes.
Mais dans le cas présent, ni l'un ni l'autre ne servait.
Pour copier une chaine dans une autre chaine, j'utilise memcpy.
ben normalement, c'est strcpy.
Lorsque l'on connaît la longueur de la chaine, je pense qu'il est préférable d'utiliser memcpy( ), a priori bien plus rapide, surtout pour des longues chaînes. Mais dans le cas présent, ni l'un ni l'autre ne servait.