J'ai un tableau int
et je dois trouver le nombre d'éléments qu'il contient. Je sais que cela a quelque chose à voir avec sizeof
mais je ne sais pas comment l'utiliser exactement.
Si vous avez votre tableau dans la portée, vous pouvez utiliser sizeof
pour déterminer sa taille en octets et utiliser la division pour calculer le nombre d'éléments:
#define NUM_OF_ELEMS 10
int arr[NUM_OF_ELEMS];
size_t NumberOfElements = sizeof(arr)/sizeof(arr[0]);
Si vous recevez un tableau en tant qu'argument de fonction ou si vous allouez un tableau dans heap, vous ne pouvez pas déterminer sa taille à l'aide de la variable sizeof
. Vous devrez stocker/transmettre les informations de taille d'une manière ou d'une autre pour pouvoir les utiliser:
void DoSomethingWithArray(int* arr, int NumOfElems)
{
for(int i = 0; i < NumOfElems; ++i) {
arr[i] = /*...*/
}
}
int a[20];
int length;
length = sizeof(a) / sizeof(int);
et vous pouvez utiliser un autre moyen pour que votre code ne soit pas codé en dur en int
Dites si vous avez un tableau array
il vous suffit de:
int len = sizeof(array) / sizeof(array[0]);
Personnellement, je pense que sizeof (a)/sizeof (* a) est plus propre.
Je préfère aussi le définir comme une macro:
#define NUM(a) (sizeof(a) / sizeof(*a))
Ensuite, vous pouvez l'utiliser dans les boucles for-loop, ainsi:
for (i = 0; i < NUM(a); i++)
Il n'est pas possible de trouver le nombre d'éléments dans un tableau sauf s'il s'agit d'un tableau de caractères. Prenons l'exemple ci-dessous:
int main()
{
int arr[100]={1,2,3,4,5};
int size = sizeof(arr)/sizeof(arr[0]);
printf("%d", &size);
return 1;
}
La valeur ci-dessus nous donne la valeur 100 même si le nombre d'éléments est égal à cinq . S'il s'agit d'un tableau de caractères, vous pouvez rechercher linéairement la chaîne nulle à la fin du tableau et augmenter le compteur au fur et à mesure de votre progression.
#include<stdio.h>
int main()
{
int arr[]={10,20,30,40,50,60};
int *p;
int count=0;
for(p=arr;p<&arr+1;p++)
count++;
printf("The no of elements in array=%d",count);
return 0;
}
SORTIE = 6
EXPLICATION
p
est un pointeur sur un tableau 1-D, et dans la boucle for(p=arr,p<&arr+1;p++)
J'ai fait p
pointer sur l'adresse de base. Supposons que son adresse de base est 1000; si nous incrémentons p
, il pointe à 1002, etc. Venons-en maintenant au concept de &arr
- Il représente fondamentalement l’ensemble du tableau, et si nous ajoutons 1 au tableau entier, c’est-à-dire &arr+1
, il donne l’adresse 1012, c’est-à-dire l’adresse du tableau 1-D suivant (dans notre cas, la taille de int est 2), donc la condition devient 1000 <1012.
Donc, fondamentalement, la condition devient
for(p=1000;p<1012;p++)
Et maintenant, vérifions l'état et comptons la valeur
p=1000
et p<1012
est true
: entrez dans la boucle, incrémentez la valeur de count
à 1.p=1002
et p<1012
la condition est true
: entrez dans la boucle, incrémentez la valeur de count
à 2.p=1010
et p<1012
est true
: entrez dans la boucle, incrémentez la valeur de count
à 6.p=1012
et p<1012
est fausse: affiche la valeur de count=6
dans l'instruction printf
.J'ai utilisé le code suivant, comme suggéré ci-dessus, pour évaluer le nombre d'éléments dans mon tableau à 2 dimensions:
#include <stdio.h>
#include <string.h>
void main(void)
{
char strs[3][20] =
{
{"January"},
{"February"},
{""}
};
int arraysize = sizeof(strs)/sizeof(strs[0]);
for (int i = 0; i < arraysize; i++)
{
printf("Month %d is: %s\n", i, strs[i]);
}
}
Ça marche bien. Autant que je sache, vous ne pouvez pas mélanger différents types de données dans des tableaux C et vous devez également avoir la même taille que tous les éléments d'un tableau (si j'ai raison). Vous pouvez donc en tirer parti avec ce petit truc:
Cette copie devrait être portable pour les tableaux 2D en C, mais dans d'autres langages de programmation, cela ne fonctionnerait pas car vous pouvez utiliser différents types de données dans des tableaux de tailles différentes (comme en Java).
Si nous ne connaissons pas le nombre d'éléments dans le tableau et quand l'entrée sera donnée par l'utilisateur au moment de l'exécution. Ensuite, nous pouvons écrire le code en tant que
CODE C:
while(scanf("%d",&array[count])==1) {
count++;
}
CODE C++:
while(cin>>a[count]) {
count++;
}
Maintenant, le compte comptera le nombre d'éléments de tableau entrés.
sizeof
renvoie la taille en octets de son argument. Ce n'est pas ce que vous voulez, mais cela peut aider.
Disons que vous avez un tableau:
int array[4];
Si vous appliquez sizeof
au tableau (sizeof(array)
), il retournera sa taille en octets, qui dans ce cas est 4 * la taille d'un int
, soit un total de peut-être 16 octets (selon votre implémentation).
Si vous appliquez sizeof
à un élément du tableau (sizeof(array[0])
), il retournera sa taille en octets, qui dans ce cas est la taille d'un int
, donc un total de peut-être 4 octets (selon votre implémentation).
Si vous divisez le premier par le second, ce sera: (4 * la taille d'un int
)/(la taille d'un int
) = 4; C'est exactement ce que tu voulais.
Donc, cela devrait faire:
sizeof(array) / sizeof(array[0])
Maintenant, vous voudriez probablement avoir une macro pour encapsuler cette logique et ne jamais avoir à repenser à la façon dont cela devrait être fait:
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
Vous avez besoin des parenthèses entourant toute la macro comme dans toute autre macro complexe, ainsi que de chaque variable, afin d'éviter des bugs inattendus liés à la priorité des opérateurs.
Maintenant, vous pouvez l’utiliser sur n’importe quel tableau comme celui-ci:
int array[6];
ptrdiff_t nmemb;
nmemb = ARRAY_SIZE(array);
/* nmemb == 6 */
Rappelez-vous que les arguments des fonctions déclarées en tant que tableaux ne sont pas vraiment des tableaux, mais des pointeurs sur le premier élément du tableau, donc cela ne fonctionnera PAS sur eux:
void foo(int false_array[6])
{
ptrdiff_t nmemb;
nmemb = ARRAY_SIZE(false_array);
/* nmemb == sizeof(int *) / sizeof(int) */
/* (maybe ==2) */
}
Mais il peut être utilisé dans des fonctions si vous passez un pointeur sur un tableau au lieu de simplement le tableau:
void bar(int (*arrptr)[7])
{
ptrdiff_t nmemb;
nmemb = ARRAY_SIZE(*arrptr);
/* nmemb == 7 */
}
Super facile.
Divisez simplement le nombre d'octets alloués par le nombre d'octets du type de données du tableau en utilisant sizeof()
.
Par exemple. étant donné un tableau entier appelé myArray
int numArrElements = sizeof(myArray) / sizeof(int);
Maintenant, si le type de données de votre tableau n'est pas constant et peut éventuellement changer, indiquez au diviseur de l'équation d'utiliser la taille de la première valeur comme taille du type de données
Par exemple.
int numArrElements = sizeof(myArray) / sizeof(myArray[0]);
La question est simple: à partir d’un tableau C++ (par exemple, x
comme dans int x[10]
), comment obtiendriez-vous le nombre d’éléments qu’il contient?
Une solution évidente est la macro suivante (définition 1) :
#define countof( array ) ( sizeof( array )/sizeof( array[0] ) )
Je ne peux pas dire que ce n’est pas correct, car cela donne la bonne réponse lorsque vous lui donnez un tableau. Cependant, la même expression vous donne quelque chose de faux lorsque vous fournissez quelque chose qui n'est pas un tableau. Par exemple, si vous avez
int * p;
then countof( p )
vous en donne toujours 1 sur une machine où un pointeur int et un int ont la même taille (sur une plate-forme Win32, par exemple).
Cette macro accepte également à tort tout objet d'une classe ayant un opérateur de fonction membre []. Par exemple, supposons que vous écrivez
class IntArray {
private:
int * p;
size_t size;
public:
int & operator [] ( size_t i );
} x;
alors sizeof( x )
sera la taille de l'objet x, pas la taille du tampon pointé par x.p
. Par conséquent, vous ne recevrez pas une réponse correcte par countof( x )
.
Nous concluons donc que la définition 1 n'est pas bonne car le compilateur ne vous empêche pas de l'utiliser à mauvais escient. Il ne réussit pas à imposer que seul un tableau peut être transmis.
Quelle est la meilleure option?
Eh bien, si nous voulons que le compilateur s'assure que le paramètre à countof est toujours un tableau, nous devons trouver un contexte dans lequel seul un tableau est autorisé. Le même contexte devrait rejeter toute expression hors tableau.
Certains débutants peuvent essayer ceci (définition 2) :
template <typename T, size_t N>
size_t countof( T array[N] )
{
return N;
}
Ils représentent, cette fonction de modèle acceptera un tableau de N éléments et renverra N.
Malheureusement, cela ne compile pas car C++ traite un paramètre de tableau de la même manière qu’un paramètre de pointeur, c’est-à-dire que la définition ci-dessus est équivalente à:
template <typename T, size_t N>
size_t countof( T * array )
{
return N;
}
Il devient maintenant évident que le corps de fonction n'a aucun moyen de savoir ce que est N.
Cependant, si une fonction attend un array reference , le compilateur s'assure que la taille du paramètre réel correspond à la déclaration. Cela signifie que nous pouvons utiliser la définition 2 avec une modification mineure (définition 3) :
template <typename T, size_t N>
size_t countof( T (&array)[N] )
{
return N;
}
Ce compte fonctionne très bien et vous ne pouvez pas le tromper en lui donnant un pointeur. Cependant, c'est une fonction, pas une macro. Cela signifie que vous ne pouvez pas l'utiliser là où une constante de temps de compilation est attendue. En particulier, vous ne pouvez pas écrire quelque chose comme:
int x[10];
int y[ 2*countof(x) ]; // twice as big as x
Pouvons-nous faire quelque chose à ce sujet?
Quelqu'un (je ne sais pas qui c'est - je viens de le voir dans un morceau de code d'un auteur inconnu) a eu une idée géniale: déplacer N du corps de la fonction vers le type de retour (par exemple, rendre la fonction retour un tableau de N éléments), on peut alors obtenir la valeur de N sans appeler la fonction.
Pour être précis, nous devons faire en sorte que la fonction retourne une référence à un tableau, car C++ ne vous permet pas de retourner directement un tableau.
La mise en œuvre de ceci est:
template <typename T, size_t N>
char ( &_ArraySizeHelper( T (&array)[N] ))[N];
#define countof( array ) (sizeof( _ArraySizeHelper( array ) ))
Certes, la syntaxe est affreuse. En effet, certaines explications sont nécessaires.
Tout d'abord, les choses de premier niveau
char ( &_ArraySizeHelper( ... ))[N];
dit que _ArraySizeHelper
est une fonction qui renvoie une référence (notez le &) à un tableau de N éléments.
Ensuite, le paramètre de fonction est
T (&array)[N]
qui est une référence à un tableau T de N éléments.
Enfin, countof
est défini comme la taille du résultat de la fonction _ArraySizeHelper
. Notez que nous n’avons même pas besoin de définir _ArraySizeHelper()
, - une déclaration suffit.
Avec cette nouvelle définition,
int x[10];
int y[ 2*countof(x) ]; // twice as big as x
devient valide, comme nous le désirons.
Suis-je heureux maintenant? Eh bien, je pense que cette définition est définitivement meilleure que les autres que nous avons visitées, mais ce n’est toujours pas ce que je veux. D'une part, cela ne fonctionne pas avec les types définis dans une fonction. C’est parce que la fonction modèle _ArraySizeHelper
attend un type accessible dans la portée globale.
Je n’ai pas de meilleure solution. Si vous en connaissez un, s'il vous plaît faites le moi savoir.
j'ai surtout trouvé un moyen facile d'exécuter la longueur d'un tableau à l'intérieur d'une boucle
int array[] = {10, 20, 30, 40};
int i;
for (i = 0; i < array[i]; i++) {
printf("%d\n", array[i]);
}