2010-10-09 3 views
1

J'ai une application C (n'utilisant pas les fonctionnalités C99) qui effectue un traitement de chaîne lourd. Puisque les longueurs de chaîne ne sont pas connues, les tampons alloués statiquement ne sont pas une option pour moi. J'ai créé une implémentation string simple qui résumera la terminaison nulle et l'expansion dynamique des tampons.Ajout de la prise en charge de la mise en forme à une implémentation de chaîne personnalisée - C

Voici à quoi ça ressemble,

struct strbuf { 
    char *buffer;   /* null terminated buffer */ 
    size_t length;   /* length of the string excluding null terminator */ 
    size_t allocated;  /* total memory allocated */ 
}; 

fonction add qui ajoute la chaîne fournie dans le tampon.

int strbuf_add(struct strbuf *string, const char *c) 
{ 
    if(string == NULL) return 0; 

    while(*c != '\0') { 
     if(!add_char(string, *c++)) 
      return 0;   
    } 

    return 1; 
} 

static int add_char(struct strbuf *string, char c) 
{ 
    size_t space_available; 

    assert(string != NULL); 

    space_available = string->allocated - string->length; 
    if(space_available <= 1) { 
     if(!grow_buffer(string)) { 
      return 0; 
     } 
    } 
    string->buffer[string->length++] = c; 
    string->buffer[string->length] = '\0'; 

    return 1; 
} 

Maintenant, je dois ajouter une nouvelle méthode quelque chose comme, addformatted qui prendra un format comme sprintf. Je me demande quelle serait la meilleure façon de faire cela? Voici mes pensées.

  1. Utilisez vsnprintf. Mais je ne suis pas sûr que ce soit portable et ait le même comportement sur toutes les plateformes.
  2. Écrire moi-même un analyseur de format. Mais cela semble être plus de travail.

Toute aide dans la mise en œuvre de ce serait génial. Je ne suis intéressé que par les solutions portables.

  • Dev Env: Linux avec GCC
  • prévu pour compiler sur MSVC
+0

Au moins, snprintf devrait être portable. –

+2

traitement de chaîne lourde en C? Tu ne peux pas utiliser awk ou perl? – Nyan

+0

3. Écrivez une fonction qui interpole vos objets stringins dans une chaîne de contrôle sprintf, puis passe la chaîne de contrôle étendue et les arguments supplémentaires à * printf. indice: varargs. Mais Nyan l'a ancré: utilisez un langage approprié à la tâche qui a de vraies chaînes en tant que types réels. – msw

Répondre

1

snprintf est le chemin à suivre et a un comportement bien défini, mais il y a quelques implémentations cassées où il renvoie les mauvaises valeurs lorsque le tampon est trop petit. Personnellement, j'ignorerais les implémentations cassées à moins que vous n'ayez vraiment besoin d'en utiliser une, ou de fournir une implémentation personnalisée de toute la famille printf pour remplacer la version du système sur de tels systèmes défectueux. Sinon, vous devez rechercher le comportement brisé de ces systèmes et savoir comment écrire des solutions de contournement. Cela peut nécessiter d'agrandir progressivement la mémoire tampon jusqu'à ce que votre appel aboutisse.

0

Lorsque vous utilisez sprintf, vous devez avoir une idée de ce que la longueur de la chaîne résultante sera, ou bien vous utilisez snprintf et protégez-vous des dépassements de tampon.

Si vous voulez ce type d'interface, vous pouvez créer une fonction qui enveloppe snprintf et prend comme argument une longueur de tampon, et augmentez la quantité de votre chaîne avant d'appeler snprintf.

Questions connexes