2009-07-14 9 views
5

J'ai un tableau C++ déclaré comme mentionné ci-dessous:longueur de calcul du tableau

CString carray[] = 
{ 
     "A", 
     "B", 
     "C", 
     "D", 
     "E" 
} 

Je veux déterminer la longueur de carray lors de l'exécution. Je fais:

int iLength = sizeof(carray)/sizeof(CString); 

Est-ce correct?

+0

Oui, même je fais de même, Comme vous, j'attends de voir s'il y a d'autres façons de le faire. –

+0

Renommer cette question en "Longueur d'un tableau en C" peut être une bonne idée. –

+3

Ceci ne "détermine" pas la longueur au moment de l'exécution; la longueur est une constante à la compilation, et l'expression donnée est constante afin que le compilateur puisse simplement l'évaluer pendant la compilation et lui substituer la valeur correcte. En outre, pensez à laisser tomber la parenthèse; sizeof n'est pas une fonction. – unwind

Répondre

16

Oui. Dans le cas où le type d'élément déclaré change, vous pouvez également écrire

int iLength = sizeof(carray)/sizeof(carray[0]); 
+0

Cela fonctionne bien pour C, mais pour C++, voir la réponse d'avakar pour une alternative améliorée. En outre, pensez à utiliser l'ordre non idiomatique de l'index de tableau pour éviter d'obtenir des informations potentiellement incorrectes de types surchargeant operator []: sizeof (array)/sizeof ([0] array) –

+1

Vous vouliez probablement dire sizeof (array)/sizeof (0 [tableau]) '. :) Idée intrigante. – avakar

+1

Pour une petite dramatisation, utilisez 'sizeof (array)/sizeof (* array)'. Facile à retenir aussi! – Saradhi

5

Ce code est correct mais dans la plupart des cas, il existe de meilleurs moyens de gérer les tableaux en C++. D'autant plus que cette méthode ne fonctionnera pas avec les tableaux de taille dynamique.

Pour de tels cas, utilisez la classe de bibliothèque standard std::vector qui représente un tableau de taille dynamique (c'est-à-dire que vous pouvez insérer et supprimer des entrées).

+2

Et boost :: array pour ceux de taille statiques. – GManNickG

1

Oui, c'est la bonne façon de le faire, mais cela ne fonctionnera que dans cette situation où la taille de la matrice est connue au moment de la compilation et est visible sur le site de l'instruction sizeof(array). Il ne fonctionnera pas avec les tableaux de taille dynamique - vous aurez besoin d'autres méthodes pour eux comme utiliser un conteneur comme stl :: vector ou passer/stocker le nombre d'éléments en tant que paramètre séparé.

0

Ce n'est pas l'exécution, c'est la compilation. La façon dont vous utilisez est correcte. Notez que Visual Studio définit une fonction _countof qui fait la même chose.

Lors de l'exécution, la longueur ne peut pas être déterminée. Vous pouvez soit garder une longueur vous-même, soit utiliser std::vector

+0

Le code existant conserve déjà la longueur du tableau. Mais quand le tableau change (tout élément est retiré du tableau), j'ai modifié la longueur du tableau .. Je ne peux pas utiliser std: vector car je dois le modifier à plusieurs endroits –

+1

Un vecteur ne se redimensionne pas quand vous retirer un élément de celui-ci. De même, lors de l'allocation d'un vecteur, il est possible que ce ne soit pas la taille que vous avez spécifiée. –

0

Si vous avez un tableau dynamique, vous devriez probablement utiliser quelque chose comme un vecteur STL. http://www.cppreference.com/wiki/stl/vector/start

Les tableaux normaux en C++ ont une taille fixe et vous devez allouer manuellement de la mémoire pour développer les fichiers dynamiques.

Si vous connaissez la taille de votre tableau au moment de la compilation, utilisez une constante plutôt qu'un calcul.

+0

J'utilise la constante, mais le tableau peut changer au moment de l'exécution (tout élément peut être supprimé ou ajouté). Si le tableau change, je dois remodifier la valeur constante. Je ne peux pas utiliser le std: vector parce que ce tableau est utilisé à plusieurs endroits. S'il vous plaît suggérer une solution de contournement pour cela –

+1

Pourquoi ne pas utiliser un 'vecteur'? Devoir l'utiliser dans de nombreux endroits n'est pas une raison. En fait, la même chose s'appliquerait à un tableau de style C. –

+0

Je ne sais pas pourquoi j'ai été modifié, mais voici quelques notions de base sur les tableaux: http://www.cplusplus.com/doc/tutorial/arrays/ – Glenn

24

Vous pouvez utiliser le modèle de fonction suivant. Si vous utilisez Boost, vous pouvez appeler le boost::size.

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

int iLength = size(carray); 

Comme d'autres l'ont déjà dit, cependant, vous devriez préférer std::vector aux tableaux de style C.

+3

+1 - pour être clair, il faut souligner que la raison pour laquelle cela devrait être utilisé en C++ (évidemment cela ne fonctionnera pas en C) est que ça va générer une erreur de compilation si vous essayez accidentellement d'utiliser un pointeur, tandis que la méthode sizeof (ptr)/sizeof (ptr [0]) donnera heureusement et silencieusement le mauvais résultat. –

6

C'est exact, comme il utilise metaprogramming comme ceci:

template <typename T, std::size_t N> 
inline std::size_t array_size(T (&)[N]) { 
    return N; 
}; 

Vous devez savoir que cela fonctionne lorsque le compilateur est de voir la définition du tableau, mais pas après avoir été passé à une fonction (où il se désintègre en un pointeur):

void f(int array[]) 
{ 
    //std::cout << array_size(array) << std::endl; // fails, at this point array is a pointer 
    std::cout << sizeof(array)/sizeof(array[0]) << std::endl; // fails: sizeof(int*)/sizeof(int) 
} 
int main() 
{ 
    int array[] = { 1, 2, 3, 4, 5 }; 
    f(array); 
    std::cout << array_size(array) << std::endl; // 5 
    std::cout << sizeof(array)/sizeof(array[0]) << std::endl; // 5 
} 
+0

'inline' est redondant ici. – avakar

+0

Meilleure réponse dans ce fil. – stepancheg

+1

@avakar: comme dans la plupart des endroits, inline peut être inutile ou ignoré, à la fin c'est juste une suggestion au compilateur. Mais ce n'est pas redondant, un compilateur pourrait décider de ne pas générer la fonction pour chaque appel en lui-même (avec ou sans l'inline, pour ce qui compte), même si la plupart des compilateurs actuels vont intégrer une si petite fonction. –

0

Lire l'article this par Ivan J. Johnson dans Dr. Dobbs Journal. Je pense que cela couvre la plupart des solutions présentées ici. Il décrit également les mérites et les démérites de chaque approche très bien.

0

SDK Windows (en-tête-à-dire windows.h) offre la ARRAYSIZE macro qui implémente cette fonctionnalité de manière sûre (c.-à-ne fonctionne pas avec des réseaux non statiques)

0

La meilleure façon est d'utiliser une macro et Utilisez cela partout où vous voulez la taille. De cette façon, vous pouvez utiliser MAX_ROWS même dans une fonction où le tableau est passé en argument.