Pour un char []
, je peux facilement obtenir sa longueur en:
char a[] = "aaaaa";
int length = sizeof(a)/sizeof(char); // length=6
Cependant, je ne peux pas faire comme ceci pour obtenir la longueur d'un char *
en:
char *a = new char[10];
int length = sizeof(a)/sizeof(char);
je sais que a
est un pointeur, de sorte que length
sera toujours 4
(ou quelque chose d'autre dans des systèmes différents).
Ma question est la suivante: comment puis-je obtenir la longueur d'un char *
après? Je sais que quelqu'un peut me défier que vous connaissez déjà son 10
parce que vous venez de le créer. Je veux le savoir parce que cette étape consistant à obtenir sa longueur risque de prendre beaucoup de temps depuis sa création et que je ne veux pas revenir en arrière pour vérifier ce nombre. De plus, je veux aussi connaître sa longueur réelle.
Pour être plus précis
length=5
?length=10
total?pour l'exemple suivant:
char *a = new char[10];
strcpy(a, "hello");
Si le char *
est terminé par 0, vous pouvez utiliser strlen
Sinon, il n'y a aucun moyen de déterminer cette information
Il n'y a que deux façons:
Si le pointeur de mémoire de votre char *
représente une chaîne C (c'est-à-dire qu'il contient des caractères dont l'octet est 0 pour marquer sa fin), vous pouvez utiliser strlen(a)
.
Sinon, vous devez stocker la longueur quelque part. En réalité, le pointeur pointe uniquement sur un char
. Mais nous pouvons le traiter comme s'il pointe vers le premier élément d'un tableau. Puisque la "longueur" de ce tableau n'est pas connue, vous devez stocker cette information quelque part.
Avec juste le pointeur, vous ne pouvez pas. Vous devrez garder la longueur que vous avez passée à new[]
ou, mieux, utiliser std::vector
pour garder trace de la longueur et libérer la mémoire une fois que vous aurez fini.
Remarque: cette réponse ne concerne que le C++, pas le C.
Utilisez simplement std::vector<char>
qui garde la taille (dynamique) pour vous. (Bonus, gestion de la mémoire gratuite).
Ou std::array<char, 10>
qui conservent la taille (statique).
Créez une structure pour conserver les informations, par exemple:
typedef struct {
char* ptr;
int size;
} my_array;
my_array malloc_array(int size)
{
my_array res;
res.ptr = (char*) malloc(size);
res.size = size;
return res;
}
void free_array(my_array array)
{
free(array.ptr);
}
Cela peut paraître maléfique et je ne l’ai pas testé, mais pourquoi ne pas initialiser toutes les valeurs d’un tableau lors de l’attribution à '\0'
et utiliser ensuite strlen()
? Cela vous donnerait votre soi-disant valeur real car il cesserait de compter à la première '\0'
qu'il rencontre.
Bien, maintenant que j'y pense, s'il vous plaît, ne faites jamais cela. À moins que vous ne vouliez atterrir dans une pile de mémoires vides.
De plus, pour la mémoire allouée ou la mémoire total, vous pouvez utiliser les fonctions suivantes si votre environnement les fournit:
char * a = new char [10];
Ma question est la suivante: comment puis-je obtenir la longueur d'un omble *
C'est très simplement. :) Il suffit d'ajouter une seule déclaration
size_t N = 10;
char *a = new char[N];
Maintenant, vous pouvez obtenir la taille du tableau alloué
std::cout << "The size is " << N << std::endl;
Beaucoup ont mentionné ici la fonction standard C std :: strlen. Mais il ne renvoie pas la taille réelle d'un tableau de caractères. Il ne renvoie que la taille du littéral de chaîne stocké.
La différence est la suivante. si prendre votre extrait de code comme exemple
char a[] = "aaaaa";
int length = sizeof(a)/sizeof(char); // length=6
alors std :: strlen (a) retournera 5 au lieu de 6 comme dans votre code.
La conclusion est donc simple: si vous devez allouer de manière dynamique un tableau de caractères, envisagez l’utilisation de la classe std::string
. Il a la taille methof et sa longueur synonyme qui permet d’obtenir la taille du tableau à tout moment.
Par exemple
std::string s( "aaaaa" );
std::cout << s.length() << std::endl;
ou
std::string s;
s.resize( 10 );
std::cout << s.length() << std::endl;
Vous pouvez implémenter vos propres fonctions new
et delete
, ainsi qu'une fonction get-size
supplémentaire:
#define CEIL_DIV(x,y) (((x)-1)/(y)+1)
void* my_new(int size)
{
if (size > 0)
{
int* ptr = new int[1+CEIL_DIV(size,sizeof(int))];
if (ptr)
{
ptr[0] = size;
return ptr+1;
}
}
return 0;
}
void my_delete(void* mem)
{
int* ptr = (int*)mem-1;
delete ptr;
}
int my_size(void* mem)
{
int* ptr = (int*)mem-1;
return ptr[0];
}
Vous pouvez également remplacer les opérateurs new
et delete
de manière similaire.
Le problème avec l'opérateur sizeof est qu'il vous renvoie la quantité de stockage nécessaire, en octets, pour stocker l'opérande.
La quantité de mémoire nécessaire pour stocker un caractère est toujours de 1 octet. Donc, sizeof(char)
retournera toujours 1.
char a[] = "aaaaa";
int len1 = sizeof(a)/sizeof(char); // length = 6
int len2 = sizeof(a); // length = 6;
C'est la même chose pour len1
et len2
car cette division de 1 n'influence pas l'équation.
La raison pour laquelle len1
et len2
portent la valeur 6 est liée au caractère de fin de chaîne '\0'
. Ce qui est aussi un caractère qui ajoute un autre caractère à la longueur. Par conséquent, votre longueur sera de 6 au lieu de 5 que vous attendiez.
char *a = new char[10];
int length = sizeof(a)/sizeof(char);
Vous avez déjà mentionné que la longueur s'avère être ici 4, ce qui est correct. Là encore, l'opérateur sizeof renvoie la quantité de stockage de l'opérande et, dans votre cas, il s'agit d'un pointeur a
. Un pointeur nécessite 4 octets de stockage et sa longueur est donc 4 dans ce cas. Puisque vous le compilez probablement en un binaire 32 bits. Si vous aviez créé un fichier binaire 64 bits, le résultat serait 8.
Cette explication pourrait être ici déjà être ici. Je veux juste partager mes deux cents.
quand new alloue un tableau, selon le compilateur (j'utilise gnu c ++), le mot devant le tableau contient des informations sur le nombre d'octets alloués.
Le code de test:
#include <stdio.h>
#include <stdlib.h>
int
main ()
{
int arraySz;
char *a;
unsigned int *q;
for (arraySz = 5; arraySz <= 64; arraySz++) {
printf ("%02d - ", arraySz);
a = new char[arraySz];
unsigned char *p = (unsigned char *) a;
q = (unsigned int *) (a - 4);
printf ("%02d\n", (*q));
delete[] (a);
}
}
sur ma machine jette dehors:
05 - 19
06 - 19
07 - 19
08 - 19
09 - 19
10 - 19
11 - 19
12 - 19
13 - 27
14 - 27
15 - 27
16 - 27
17 - 27
18 - 27
19 - 27
20 - 27
21 - 35
22 - 35
23 - 35
24 - 35
25 - 35
26 - 35
27 - 35
28 - 35
29 - 43
30 - 43
31 - 43
32 - 43
33 - 43
34 - 43
35 - 43
36 - 43
37 - 51
38 - 51
39 - 51
40 - 51
41 - 51
42 - 51
43 - 51
44 - 51
45 - 59
46 - 59
47 - 59
48 - 59
49 - 59
50 - 59
51 - 59
52 - 59
53 - 67
54 - 67
55 - 67
56 - 67
57 - 67
58 - 67
59 - 67
60 - 67
61 - 75
62 - 75
63 - 75
64 - 75
Je ne recommanderais pas cette solution (le vecteur est meilleur), mais si vous êtes vraiment désespéré, vous pouvez trouver une relation et pouvoir conclure le nombre d'octets alloués à partir du tas.
Dans C++17
(ou plus récent), vous pouvez utiliser std::string_view
en tant que wrapper zéro pour les littéraux de chaîne.
Vous pouvez trouver la longueur d'une chaîne char * comme ceci:
char* mystring = "Hello World";
int length = sprintf(mystring, "%s", mystring);
sprintf () imprime le mystère sur lui-même et renvoie le nombre de caractères imprimés.
Vous pouvez créer un caractère de suivi, par exemple, vous pouvez ajouter n'importe quel caractère spécial, par exemple, "%" à la fin de votre chaîne, puis vérifier l'occurrence de ce caractère.
Mais c'est une manière très risquée que ce personnage puisse être ailleurs aussi dans le personnage *
char* stringVar = new char[4] ;
stringVar[0] = 'H' ;
stringVar[1] = 'E' ;
stringVar[2] = '$' ; // back-tracker character.
int i = 0 ;
while(1)
{
if (stringVar[i] == '$')
break ;
i++ ;
}
// i is the length of the string.
// you need to make sure, that there is no other $ in the char*
Sinon, définissez une structure personnalisée pour suivre la longueur et allouer de la mémoire.