OVH Cloud OVH Cloud

memcpy et char

50 réponses
Avatar
Alain CROS
Bonjour.

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);
}

10 réponses

1 2 3 4 5
Avatar
Harpo
Alain CROS wrote:

Bonjour.

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 ) ;
}

Avatar
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.


Avatar
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



Avatar
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.



Avatar
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.

Avatar
Targeur fou

Salut,

Targeur fou wrote on 23/09/05 :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

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


Avatar
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)




Avatar
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 <><><><><><><><>

Avatar
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.


Avatar
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.


1 2 3 4 5