2010-07-18 5 views
3

I ont une carbonisation buf [x], s int et void * data.C - chaîne lu à partir du tampon d'une certaine taille

Je veux écrire une chaîne de taille s en données de buf.

Comment faire cela?

Merci d'avance.

+2

Est-ce que 'buf' est une chaîne délimitée par des zéros ou sa taille est-elle définie par' s'? Essayez-vous de copier seulement une partie de la chaîne? Qu'est-ce que 'x'? La chaîne copiée dans 'data' doit-elle être délimitée par des zéros? Qu'avez-vous essayé jusqu'à présent? – zvone

+0

note que caf a souligné plusieurs erreurs dans ma réponse. J'ai édité ma réponse pour tenir compte de ses commentaires. – Gilles

Répondre

4

En supposant que

  • par "chaîne", vous voulez dire une chaîne terminée par un zéro, comme cela est normalement signifié dans C;
  • vous n'avez pas encore alloué de mémoire dans data;
  • vous savez déjà que s = x <

D'abord, vous devez allouer de la mémoire dans data. Ne pas oublier la pièce pour le 0 octet à la fin de la chaîne.

data = malloc(s+1); 
if (data == NULL) { 
    ... /*out-of-memory handler*/ 
} 

En supposant malloc réussit, vous pouvez maintenant copier les octets.

EDIT:

La meilleure fonction pour le travail, comme l'a souligné café, est strncat. (Il est entièrement portable, faisant partie de C89.) Il ajoute à la chaîne de destination, donc prendre des dispositions pour la destination à une chaîne vide au préalable:

*(char*)data = 0; 
strncat(data, buf, s); 

D'autres possibilités de qualité inférieure, gardé ici pour servir d'exemples de fonctions connexes:

  • Si vous ont strlcpy (ce qui est la norme C mais est commun sur les systèmes Unix modernes, il existe des implémentations de domaine public flottant autour):

    strlcpy(data, buf, s+1); 
    
  • Si vous savez qu'il ya au moins s caractères dans la chaîne source, vous pouvez utiliser memcpy:

    memcpy(data, buf, s); 
    

    ((char *) données) [s + 1] = 0;

  • Sinon, vous pouvez calculer la longueur de la chaîne source première:

    size_t bytes_to_copy = strlen(buf); 
    if (bytes_to_copy > s) bytes_to_copy = s; 
    memcpy(data, buf, bytes_to_copy); 
    ((char*)data)[s+1] = 0; 
    
  • Ou vous pouvez utiliser strncpy, mais il est inefficace si la longueur réelle de la chaîne source est beaucoup plus petite que s:

    strncpy(data, buf, s); 
    ((char*)data)[s+1] = 0; 
    
+2

Vos implémentations de 'memcpy()' ont des bogues - elles placent toutes deux incorrectement le terminateur nul, et elles essaient de déréférencer un 'void *', ce que vous ne pouvez pas faire. Le premier devrait utiliser '((char *) data) [s] = 0', et le second devrait utiliser' ((char *) data) [bytes_to_copy] = 0; '. Pour le dernier, au lieu de 'strncpy()' vous pouvez utiliser 'strncat()': '((char *) data) [0] = 0; strncat (data, buf, s); ' – caf

+0

@caf: vous avez raison sur les deux points. Malheureusement ma réponse a été acceptée, donc je l'ai édité plutôt que de la supprimer parce que je ne veux pas laisser une mauvaise réponse trop visible. Mais si vous écrivez une réponse strncat, je vais l'augmenter. – Gilles

2
memcpy(data, buf, s); 

Cela suppose que vous avez suffisamment d'espace dans les données (et dans buf). En fonction de ce que vous faites (vous ne dites pas, mais vous dites que vous copiez des chaînes), vous pouvez ajouter une valeur nulle à la fin de votre chaîne nouvellement copiée si vous n'avez pas copié une valeur nulle déjà en cours, et vous allez utiliser des données dans une fonction qui attend des chaînes.

2
data = malloc(s); 
strcpy((char*)data,buf); 
free(data); 
3

Si data est pas affectée:

char buf[] = "mybuffer"; 
void *data = malloc(strlen(buf)+1); 
strcpy((char*)data,buf); 

En fait, si les données sont vraiment à définir, vous pouvez également faire

char buf[] = "mybuffer"; 
void *data= (void*)strdup(buf); 
+2

Vous devriez 'malloc (strlen (buf) +1)' – sje397

+0

Les littéraux de chaîne ne sont-ils pas déjà terminés par un caractère nul? – Jack

+0

Oui, et ici 'buf' est null-terminé même si [ce n'est pas un littéral de chaîne] (http://c-faq.com/aryptr/aryptr2.html). Mais 'strlen (buf)' n'inclut pas l'octet de terminaison dans son compte. – Gilles

2
int n = MIN((x - 1), s); 
char *bp = buf; 
char *dp = (char *)data; 
while (n--) { 
    *bp++ = *dp++; 
} 
*dp = '\0'; 
Questions connexes