11
votes

Comment déterminer la fin d'un tableau entier lors de la manipulation avec un pointeur entier?

Voici le code: xxx pré>

pour la matrice de caractères: (puisque nous avons un caractère null à la fin, aucun problème tout en itération) P>

char myChar[] ={ 'A', 'B', 'C', 'D', 'E', '\0' };
char *myCharPtr = &myChar[0];
while( *myCharPtr != NULL )
{
    cout<<*myCharPtr<<endl;
    myCharPtr++;
}

Output: ABCDE


0 commentaires

11 Réponses :


11
votes

en C ++ La meilleure solution consiste à utiliser un std :: vecteur, pas un tableau. Les vecteurs portent leur taille avec eux. Le problème avec l'utilisation de zéro (ou de toute autre valeur) en tant que marqueur d'extrémité est que cela ne peut bien sûr pas apparaître ailleurs dans le tableau. Ce n'est pas tellement un problème pour les chaînes, car nous souhaitons rarement imprimer le caractère avec le code zéro, mais c'est un problème lors de l'utilisation de tableaux d'INTS.


6 commentaires

Je vais bien avec STD :: Vecteur ici. Une question générale que j'ai. Comment dans les vecteurs, ils sont capables de déterminer la taille du tableau entier?


@Akn ils portent la taille autour d'une valeur distincte de quelque sorte.


@Akn the STD: Vector n'est pas simplement un tableau, c'est probablement une structure qui contient un tableau et une intensive pour la longueur et éventuellement plus.


Je ne suis pas d'accord avec cela "en C ++ la meilleure solution consiste à utiliser un std :: vecteur". Les tableaux font partie de C ++ et sont utiles dans de nombreux contextes. Pourquoi utilisez-vous un vecteur s'il n'est pas nécessaire de modifier la taille de la matrice?


@Vicente fonctionne comme une récupération facile de taille, accès à l'élément vérifié via (), etc.


Bon point pour l'accès vérifié via à. Je ferai une proposition de booster, qui savait peut-être que cela pourrait entraîner une addition au C ++ 0x un jour :) Vous pouvez avoir la même chose à l'aide d'un tableau et des fonctions gratuites C ++ 0x ou Boost.Range XXX :: Taille (ARR) et XXX :: AT (ARR, IDX) Lorsque XXX peut être STD ou Boost en fonction de vos contraintes. Ces fonctions fonctionnelles sont plus adaptées à la programmation générique.



3
votes

Vous pouvez certainement décider de votre propre "Sentinel" Valeur pour stocker à la fin de votre éventail d'entiers. Si vos entiers sont toujours censés être non négatifs, par exemple, vous pouvez utiliser -1 comme valeur sentinelle qui marque la fin de la matrice.

int myInt[] ={ 1, 2, 3, 4, 5, -1 };
int *myIntPtr = &myInt[0];
while( *myIntPtr >= 0 )
{
    cout<<*myIntPtr<<endl;
    myIntPtr++;
}


0 commentaires

1
votes

La valeur de caractère 0 a une signification particulière, normalisée par la convention et la pratique. La valeur INT 0 ne le fait pas, donc cela ne peut pas être une règle générale. Si cela fonctionne dans votre cas spécifique, vous pouvez y aller. Cependant, en général, il est préférable de garder une trace de la longueur des baies entières séparément, car cela fonctionne universellement. Ou utiliser std :: vecteur ou un conteneur similaire qui gère ce travail pour vous.


0 commentaires

0
votes

Utiliser std :: Vecteur, comme Neil dit.

ou faites-le l'itérateur Way: P>

int myInt[] ={ 100, 200, 300, 400, 500 };
int *myIntPtr = &myInt[0];
int *myIntPtr_end = myIntPtr + 5;
while(myIntPtr != myIntPtr_end)
  {
  cout<<*myIntPtr<<endl;
  ++myIntPtr;
  }


3 commentaires

Ici, nous voyons «5» et un succès qui est la longueur que nous pouvons utiliser directement à droite! :)


INT * MYINTPTR_END = MYTINTPTR + 5; Le pointeur * myintPtr_end est pointant sur quelque_junk_value après la dernière valeur. (C'est-à-dire) après 500 ans. Depuis cette défaute, je pense que ce n'est pas conseillé. Que dise?


Peu importe que cela souligne de la malbouffe, tant que vous n'avez pas la désesponseur du pointeur. Quant à la longueur de la matrice - vous l'avez évidemment disponible dans votre exemple. Si vous parlez de pointeurs-to-tableaux sans aucune information sur la longueur, c'est quelque chose que vous devez ajouter à votre question / description.



3
votes

2 commentaires

Parce qu'il n'y a pas de telle chose - vous pensez à Taillef. Et cela ne peut pas être utilisé une fois que la matrice est décrite à un pointeur.


@Neil Butterworth Merci, c'était juste un cas d'accusation de displexie :) Cependant, rien n'indique de ne pas pouvoir accéder à la matrice. Cela peut également être utilisé à la suite de la mise en oeuvre de quelque chose comme une classe de modèles de matrice de vérification des limites.



0
votes
for(i=0; i < sizeof(myInt); i++ )
{
    cout<<*myIntPtr<<endl;
    myIntPtr++;
}
If you're suggesting your code where myIntPtr is manipulated has no idea of the chunk size it points to, you either have to decide for a magic value in your int array, or restructure your code so that sizeof(myInt) is also available.Standard C library functions use the latter approach: whenever you need to pass a buffer area through a pointer, you have to pass them its size in the same call.

1 commentaires

Merci Kostas. Mais Tailleof (Myint) ne donnera pas directement à la taille de la matrice. Donc, cela peut plutôt être remplacé par 'int NinTarrsize = Tailleof (Myint) / Tiplazof (int)'



14
votes

La convention C-Strings est qu'un char * fini par un caractère '\ 0'. Pour le tableau ou tout autre conteneur C ++, d'autres idiomes peuvent être appliqués. Suivant suit mes préférences

Le meilleur moyen d'itérer sur des séquences consiste à utiliser la boucle de plage de la plage incluse sur C ++ 0x xxx

si votre compilateur Don ' t Fournir cela encore, utilisez les itérateurs xxx

et si vous ne pouvez pas utiliser ni std :: début / fin xxx

PS Boost.foreach émule la boucle de plage sur la plage sur C ++ 98 compilateurs


5 commentaires

Où est std :: début / fin défini? Vient-il avec C ++ 0x?


@Christian: Oui, ou avec boost.


@Christian Oui Ceci est une nouvelle fonctionnalité de C ++ lié à la gamme. Boost.Range inclut cela et bien plus encore, ce qui simplifie beaucoup l'algorithme sur des séquences.


Votre dernier exemple est incorrect. Il devrait être IT! = & Array [TIMILOFOF (tableau) / TIMITEOF (* TRAY)], comme Tailleof` renvoie la taille de la matrice en octets, pas des éléments.


La taille de Int est 2, lorsqu'un tableau INT est initialisé, sa taille sera de 2 * Nombre d'éléments de réseau, il imprimera donc 10 éléments dans votre cas, dont 5 seront les valeurs nécessaires et 5 seront des valeurs de déchets.



1
votes

Tout d'abord, nous ne "ajoutons pas de caractère null" à la fin de la chaîne. Il n'y a pas de "caractère nul". Nous ajoutons zéro caractère, ce qui est parfois appelé "caractère nul". Mais null n'a absolument rien à voir avec cela. NULL est normalement utilisé dans le contexte du pointeur et non dans le contexte de caractère ou entier. Vos comparaisons comme * mycharptr! = Null ou * myintptr! = Null compilera (en raison de la manière dont null est défini dans C ++), mais ne faites pratiquement aucun sens. Si vous recherchez un caractère zéro dans un tableau, vous pouvez le vérifier comme * mycharptr! = '\ 0' ou comme * mycharptr! = 0 ou comme tout simplement * mycharptr , mais jamais comme * mycharptr! = null .

Deuxièmement, le caractère zéro est appelé zéro caractère pour une raison: il est égal à l'entier zéro. Type de caractère en C ++ n'est qu'un type entier simple après tout. La seule raison pour laquelle nous pouvons utiliser zéro caractère car quelque chose de spécial dans le contexte de la chaîne est parce que c'est la signification est réservée à cet objectif spécifique. En général, dans le contexte entier Réservez zéro à cet effet est clairement impossible pour des raisons évidentes: zéro est aussi utile que toute autre valeur entière. Pourtant, si dans votre application spécifique entier zéro peut être utilisé comme valeur réservée, n'hésitez pas à l'utiliser de cette façon. Ou vous pouvez utiliser toute autre valeur entière à cette fin. Mais en général, en faisant référence à la question que vous posez dans le titre, il y a aucun mode pour déterminer la fin d'un tableau. Il est de votre responsabilité de savoir où se trouve la fin (en connaissant le nombre total d'éléments ou en marquant la fin avec une valeur réservée de votre choix ou d'une autre manière). Il n'ya aucun moyen de déterminer la fin d'un tableau même avec des chaînes, car tout ce que vous pouvez espérer, c'est de trouver la fin de la chaîne ou de la chaîne , ce qui n'est pas nécessairement la fin de la matrice qui stocke cette chaîne.

Si vous avez explicitement ajouté un zéro à la fin de votre réseau entier, votre premier cycle s'arrêterait judicieusement. Pour une raison quelconque, vous avez explicitement ajouté \ 0 à la fin de votre tableau de caractères (et le deuxième cycle arrête), mais vous n'avez pas ajouté de zéro à la fin de votre réseau entier (et le premier cycle ne s'arrête pas). Vous vous demandez pourquoi votre premier cycle ne s'est pas arrêté à zéro? Parce que tu n'as pas mis ça zéro là-bas. C'est si simple.


0 commentaires

1
votes

La norme ASCII et UNICODE définit un caractère avec une valeur 0 en tant que caractère NULL, pas un marqueur de fin de rangée / chaîne. Ce n'est que la convention C / C ++ que les chaînes sont terminées avec ce caractère. Pascal utilise une notation différente. De plus, le caractère nul ne indique pas nécessairement la fin de la matrice contenant la chaîne. Il existe plusieurs fonctions de l'API Win32 qui utilisent des chaînes à double terminaison Double NULL (la boîte de dialogue Ouvrir le fichier pour une), comme ceci:

"one\0two\0three\0" // there's an implicit '\0' appended in C/C++


0 commentaires

0
votes

La manière générique de créer le pointeur de fin de n'importe quel tableau est la suivante: Déterminez d'abord le nombre d'éléments dans la matrice à l'aide de Tailleof (tableau) / Tailleof (tableau [0]) . Notez que la taille de l'apparition de deux fois parce qu'elle renvoie la taille d'un élément en octets. Donc, pour un tableau statique, la taille de la matrice est divisée par la taille d'un élément de la matrice. Ensuite, le pointeur final à un tableau est Array + Number_Of_elements . Donc, cela devrait fonctionner: xxx

et maintenant pour certaines mises en garde:

  • Le pointeur de fin pointe sur un endroit juste après la fin de la matrice! Donc, * myintptr retourne la malbouffe, pas la valeur du dernier élément de la matrice.
  • Ceci est seulement bon pour les tableaux statiques réguliers! pour les conteneurs, utilisez le commencer et fin fonctions membres et itérateurs.
  • Cette approche fonctionnera avec n'importe quelle version de C ++. Toutefois, si vous utilisez C ++ - 11 ou plus tard, il est conseillé d'utiliser le std :: Commencez et std :: End Fonctions dans la relevé de vue comme suit: < / p>

    pour (int * myintptr = std :: commence (myint); myintptr! = std :: fin (myintptr); myintptr ++)

  • Cette méthode est destinée à être prise en compte en plus des autres réponses. Lequel est le meilleur est une question de contexte.


0 commentaires

0
votes

Utiliser Tailleof () peut résoudre le problème

int arr[] = {10, 20};                                                                                                                                                               
int *p = arr;                                                                                                                                                                       
int loop = sizeof(arr);                                                                                                                                                                                                                                                                                                                                                 

while (loop) {                                                                                                                                                                             
   cout<<*p++<<endl;                                                                                                                                                          
   loop-=sizeof(int);                                                                                                                                                           
}


0 commentaires