2009-03-31 5 views
0

J'ai une structure qui a un tableau de pointeurs. Je voudrais insérer dans les chiffres de tableau dans le format de chaîne, c.-à-d. "1", "2", etc.C: utilisation de sprintf et strncpy insertion de données dans un tableau de pointeurs

Cependant, y a-t-il une différence dans l'utilisation de sprintf ou de strncpy?

Des grosses erreurs avec mon code? Je sais que je dois appeler gratuitement, je le ferai dans une autre partie de mon code.

Un grand merci pour tout conseil!

struct port_t 
{ 
    char *collect_digits[100]; 

}ports[20]; 

/** store all the string digits in the array for the port number specified */ 
static void g_store_digit(char *digit, unsigned int port) 
{ 
    static int marker = 0; 
    /* allocate memory */ 
    ports[port].collect_digits[marker] = (char*) malloc(sizeof(digit)); /* sizeof includes 0 terminator */ 
    // sprintf(ports[port].collect_digits[marker++], "%s", digit); 
    strncpy(ports[port].collect_digits[marker++], digit, sizeof(ports[port].collect_digits[marker])); 
} 

Répondre

3

Oui, votre code a quelques problèmes.

  • En C, ne pas utiliser la valeur de retour de malloc(). Ce n'est pas nécessaire, et peut cacher des erreurs.
  • Vous allouez de l'espace en fonction de la taille d'un pointeur et non de la taille de ce que vous souhaitez stocker.
  • La même chose pour la copie.
  • On ne sait pas ce que le statique fait, et si la logique autour est vraiment correcte. Est-ce que port est l'emplacement qui va être modifié ou est-il contrôlé par une variable statique?

Voulez-vous stocker uniquement des chiffres uniques par emplacement dans la matrice ou des nombres à plusieurs chiffres?

Voilà comment cette fonction pourrait ressembler, compte tenu de la déclaration:

/* Initialize the given port position to hold the given number, as a decimal string. */ 
static void g_store_digit(struct port_t *ports, unsigned int port, unsigned int number) 
{ 
    char tmp[32]; 

    snprintf(tmp, sizeof tmp, "%u", number); 
    ports[port].collect_digits = strdup(tmp); 
} 
1

La première chose: pourquoi avoir un tableau de pointeurs? Attendez-vous plusieurs chaînes pour un objet port? Vous n'avez probablement besoin que d'un tableau ou d'un pointeur (puisque vous êtes malloc -ing plus tard).

struct port_t 
{ 
    char *collect_digits; 
}ports[20]; 

Vous devez passer l'adresse de la chaîne, sinon, le malloc agit sur une copie locale et vous ne retournent jamais ce que vous avez payé pour.

static void g_store_digit(char **digit, unsigned int port); 

Enfin, le sizeof applique dans un contexte de pointeur et ne vous donne pas la bonne taille.

+0

L'opérateur sizeof ne s'applique certainement pas uniquement aux baies. {int x; printf ("x est% d caractères \ n", sizeof x); } est parfaitement valide, pas de tableau en vue. – unwind

+0

@unwind: Bien sûr. Je voulais dire dans ce contexte. – dirkgently

1

Au lieu d'utiliser malloc() et strncpy(), il suffit d'utiliser strdup() - il alloue suffisamment bac tampon pour maintenir le contenu et copie le contenu de la nouvelle chaîne, tout en un coup. Du tout, vous n'avez pas du tout besoin de g_store_digit() - utilisez simplement strdup() et maintenez au niveau de l'appelant.

2
strncpy(ports[port].collect_digits[marker++], digit, sizeof(ports[port].collect_digits[marker])); 

Ceci est incorrect.

Vous avez alloué à collect_digits une certaine quantité de mémoire.

Vous copiez des caractères char * dans cette mémoire.

La longueur que vous devez copier est strlen (chiffres). Ce que vous êtes en train de copier, c'est sizeof (ports [port]).collect_digits [marqueur]), ce qui vous donnera la longueur d'un seul caractère *.

Vous ne pouvez pas utiliser sizeof() pour trouver la longueur de la mémoire allouée. De plus, à moins que vous sachiez a priori que les chiffres ont la même longueur que la mémoire allouée, même si sizeof() vous indique la longueur de la mémoire allouée, vous copiez le mauvais nombre d'octets (trop, vous seul besoin de copier la longueur des chiffres). De même, même si les deux longueurs sont toujours les mêmes, l'obtention de la longueur est de cette manière non expressive; cela induit le lecteur en erreur.

Notez également que strncpy() remplira les NULL de fin si la longueur de copie spécifiée est supérieure à la longueur de la chaîne source. En tant que tel, si les chiffres est la longueur de la mémoire allouée, vous aurez une chaîne non-terminée. La ligne sprintf() est fonctionnellement correcte, mais pour ce que vous faites, strcpy() (par opposition à strncpy()) est, d'après ce que je peux voir et connaître du code, le bon choix. Je dois dire, je ne sais pas ce que vous essayez de faire, mais le code semble très gênant.

1

Un autre problème avec le code original: La déclaration

strncpy(ports[port].collect_digits[marker++], digit, sizeof(ports[port].collect_digits[marker])); 

références et marker++ dans la même expression. L'ordre d'évaluation pour le ++ est undefined dans ce cas - la seconde référence à peut être évaluée avant ou après que l'incrément soit effectué.

Questions connexes