2009-05-22 8 views
5

Je suis relativement nouveau en C++. Les affectations récentes ont nécessité que je convertisse une multitude de tampons char (de structures/sockets, etc.) en chaînes. J'ai utilisé des variations sur les éléments suivants, mais ils semblent maladroits. Y a-t-il une meilleure façon de faire ce genre de chose?De bonnes méthodes pour convertir des tampons de tableau char en chaînes?

#include <iostream> 
#include <string> 

using std::string; 
using std::cout; 
using std::endl; 


char* bufferToCString(char *buff, int buffSize, char *str) 
{ 
    memset(str, '\0', buffSize + 1); 
    return(strncpy(str, buff, buffSize)); 
} 


string& bufferToString(char* buffer, int bufflen, string& str) 
{ 
    char temp[bufflen]; 

    memset(temp, '\0', bufflen + 1); 
    strncpy(temp, buffer, bufflen); 

    return(str.assign(temp)); 
} 



int main(int argc, char *argv[]) 
{ 
    char buff[4] = {'a', 'b', 'c', 'd'}; 

    char str[5]; 
    string str2; 

    cout << bufferToCString(buff, sizeof(buff), str) << endl; 

    cout << bufferToString(buff, sizeof(buff), str2) << endl; 

} 

Répondre

15

Étant donné vos chaînes d'entrée ne sont pas nulles fin, vous ne devriez pas utiliser str ... fonctions. Vous ne pouvez pas non plus utiliser le std::string constructors couramment utilisé. Cependant, vous pouvez utiliser ce constructeur:

std::string str(buffer, buflen): il faut un char* et une longueur. (en fait const char* et la longueur)

Je voudrais éviter la version de la chaîne C. Cela donnerait:

std::string bufferToString(char* buffer, int bufflen) 
{ 
    std::string ret(buffer, bufflen); 

    return ret; 
} 

Si vous devez vraiment utiliser la version C-string, soit déposer une 0 à la position bufflen (si vous pouvez) ou créer un tampon de bufflen+1, puis memcpy le tampon en elle, et déposez un 0 à la fin (position bufflen).

+4

Pour Newton Falls: notez que std :: string (Ch * p, taille_type n) ne s'arrêtera pas aux caractères null s'il y en a dans le buffer; tous les n caractères seront copiés dans la chaîne. – outis

+0

Merci Simon. J'ai complètement oublié ce constructeur. Ceci ou la suggestion de David Dolson de la gamme ctor semble une bien meilleure solution que ce que je faisais. –

+0

Je suis complètement d'accord pour éviter la version de chaîne C si elle est posible. Traiter avec des cstrings bruts ne vous mènera à des ennuis ces jours-ci. Il y a plusieurs bugs dans votre bufferToCString, y compris l'écrasement de la mémoire inconnue en utilisant bufsize + 1, et en supposant que votre tampon de sortie 'str' est bufsize + 1 du buffer d'entrée. Ces bugs s'exposent de manière subtile et vous causent beaucoup de douleur de débogage. Utilisez simplement std :: string si vous le pouvez. –

1

std :: string à const char *:

my_str.c_str(); 

char * à std :: string:

string my_str1 ("test"); 
    char test[] = "test"; 
    string my_str2 (test); 

ou même

string my_str3 = "test"; 
+0

Le problème est que le tampon n'a pas de nulle de fin. –

+0

Lorsque vous initialisez un tableau de char avec une chaîne constante, il obtient une valeur nulle finale. Lorsque vous utilisez string :: c_str(), vous obtenez également une valeur nulle finale. Je ne comprends pas quelle est votre plainte. –

+0

Le code de la réponse est correct mais n'est pas identique à la question. "char buff [4] = {'a', 'b', 'c', 'd'};" ne vous donne pas une chaîne terminée par zéro. – markh44

0
std::string buf2str(const char* buffer) 
{ 
    return std::string(buffer); 
} 

O r juste

std::string mystring(buffer); 
+0

Je cherchais un moyen plus propre d'ajouter une terminaison nulle pour que quelque chose comme ça fonctionne correctement. –

1

Si le tampon de données contient des caractères null ('\ 0'), vous ne souhaitez pas utiliser les opérations terminées par un caractère nul.

Vous pouvez utiliser le constructeur qui prend char *, length.

char buff[4] = {'a', 'b', 'c', 'd'}; 
cout << std::string(&buff[0], 4); 

Ou vous pouvez utiliser le constructeur qui prend une gamme:

cout << std::string(&buff[0], &buff[4]); // end is last plus one 

Ne pas utiliser le std :: string (buff) constructeur avec le buff tableau [] ci-dessus, parce que ce n'est pas nul -terminé.

+0

Merci David. C'est une bonne alternative à la réponse de Simon. –

0

Utilisation constructeur de chaîne qui prend la taille:

string (const char * s, size_t n); 

contenu est initialisé à une copie de la chaîne formée par le premier n caractères dans le tableau de caractères pointé par s.

cout << std::string(buff, sizeof(buff)) << endl; 

http://www.cplusplus.com/reference/string/string/string/

tampon à terminaison non-nulle à la chaîne C:

memcpy(str, buff, buffSize); 
str[bufSize] = 0; // not buffSize+1, because C indexes are 0-based. 
0

Le procédé a besoin de connaître la taille de la chaîne. Vous devez soit:

  1. en cas de char * passer la longueur méthode
  2. en cas de char * désignant null se terminant tableau de caractères, vous pouvez utiliser tout jusqu'à null caractère
  3. pour char [], vous pouvez utiliser des modèles pour déterminer la taille du char []

1) par exemple - pour les cas où vous passez le bufflen:

std::string bufferToString(char* buffer, int bufflen) 
{ 
    return std::string(buffer, bufflen); 
} 

2) par exemple - pour le cas où la mémoire tampon est de points à null réseau à terminaison de caractères:

std::string bufferToString(char* buffer) 
{ 
    return std::string(buffer); 
} 

3) par exemple - pour les cas où l'on passe char []:

template <typename T, size_t N> 
std::string tostr(T (&array)[N]) 
{ 
    return std::string(array, N); 
} 


Usage: 
char tstr[] = "Test String"; 
std::string res = tostr(tstr); 
std::cout << res << std::endl; 

Pour les 2 premiers cas, vous n'avez pas besoin de créer une nouvelle méthode:

std::string(buffer, bufflen); 
std::string(buffer); 
0

valeur de chaîne (reinterpret_cast (buffer), length);

+0

Veuillez expliquer votre réponse. – JayIsTooCommon

Questions connexes