1
votes

Gestion des tableaux en C et C #

J'ai essayé d'insérer un élément dans un tableau et cela a échoué avec un index de tableau hors limites

J'ai essayé en C # cela a échoué cela fonctionne bien en c

int LA[] = {1,3,5,7,8};
int item = 10, k = 3, n = 5;
int i = 0, j = n;
n = n + 1;
while( j >= k) {
    printf("j+1 =%d",j+1);
    LA[j+1] = LA[j];
    j = j - 1;
}

mais cela fonctionne en c

int[] LA = {1,3,5,7,8};
int item = 10, k = 3, n = 5;
int i = 0, j = n;   
n = n + 1;
while( j >= k) 
{
    LA[j+1] = LA[j];
    j = j - 1;
}
LA[k] = item;

Quelqu'un peut-il expliquer pourquoi? et qu'en est-il des autres langues, cela continuera-t-il à varier? Merci.

De nombreuses réponses disent que cela ne fonctionne pas dans c, j'ai donc téléchargé une image ! [entrez la description de l'image ici] 1

c c#

12 commentaires

Dans le cas de C #, essayez d'utiliser List : List LA = ... LA.Insert (index, value);


" index de tableau hors limites " signifie quelque part, à un moment donné, votre code essaie d'utiliser une valeur d'index de tableau qui est hors des limites du tableau donné. Je veux dire, " index de tableau hors limites " signifie qu'un index de tableau est hors limites ... En ce qui concerne l'insertion d'un élément: les tableaux sont de taille fixe, donc "l'insertion" d'un élément dans un tableau nécessiterait soit de supprimer / remplacer un autre élément du tableau, soit de recréer le tableau avec une taille plus grande. Ou utilisez un type de collection redimensionnable (comme List suggéré dans le premier commentaire) \


@DmitryBychenko dans ce cas, l'erreur est qu'il lit depuis LA [6] , donc utiliser une List n'aidera pas.


votre modification manque le point: vous vous trompez - vous pouvez penser que cela "fonctionne" en C; ce n'est pas - vous avez fait quelque chose de très mal et jusqu'à présent cela ne vous a pas fait de mal; c'est tout; ça ne marche pas"


btw: je peux aussi "réparer" le C #, regardez! int * LA = stackalloc int [] {1, 3, 5, 7, 8}; - c'est fait! cela "fonctionnera" aussi pour les mêmes raisons (c'est-à-dire: il est également cassé) - les raisons étant ici: votre tableau C n'est pas vérifié par les limites (tout comme mon pointeur C #); vous avez alors accédé à la mémoire après la fin de la plage définie - cela pourrait être de la mémoire inutilisée, cela pourrait être quelque chose de vraiment important, cela pourrait être une page invalide; à ce stade: votre code est juste cassé


@MarcGravell de par son attitude, je soupçonne de lui donner que C # est une mauvaise idée - il l'utilisera juste comme sa "solution"


C # a moins de démons nasaux . C'est quelque chose qui facilite le C #; vous obtenez un message d'erreur maintenant plutôt qu'un bogue très difficile à trouver des semaines plus tard.


@Marc Gravell Donc, cela signifie-t-il que c en général n'est pas vérifié, est-ce une sorte de bogue dans l'environnement


Les tableaux @nevas C (qui, lorsqu'ils sont indexés dans, sont essentiellement les mêmes que les expressions de pointeur) ne sont en effet pas des limites vérifiées; c'est une caractéristique de la langue et de ce concept; si vous voulez un type vérifié par les limites: n'utilisez pas de tableaux bruts (/ pointeurs)


@nevas: les accès aux tableaux en C ne sont pas vérifiés. Tenter d'accéder à un élément du tableau en dehors de la plage du tableau conduit à un comportement indéfini , ce qui signifie que le compilateur ou l'environnement d'exécution ne sont pas tenus de faire quoi que ce soit en particulier. Votre code peut sembler fonctionner comme prévu, ou il peut corrompre d'autres données, ou il peut tomber en panne.


@MarcGravell: Mieux. Je vais supprimer mon commentaire.


Remplacez int [] LA = {1,3,5,7,8}; par int [] LA = {1,3,5,7,8, -1}; < / code> pour avoir un élément vide supplémentaire à la fin du tableau. La même chose est nécessaire pour la version C.


3 Réponses :


5
votes

Oh non, cela ne "marche" pas, cela semble assez flagrant d'écriture hors des limites, et ainsi vous obtenez un comportement indéfini. Vous ne pouvez pas développer dynamiquement un tableau en C, ils sont dimensionnés statiquement au point de "création".

Notez que C ne dit pas que faire des choses indéfinies entraînera un résultat mesurable particulier [*], donc il peut sembler faire la chose prévue, mais toujours complètement cassé .

[*]: C'est ce que signifie "indéfini": il n'y a aucune définition de ce qui va se passer. Certaines personnes semblent l'interpréter comme "nous allons obtenir le gestionnaire d'erreurs pour déclencher cette chose qu'ils appellent" comportement indéfini "", mais ce n'est pas vrai. Tout peut arriver, n'importe quoi.


3 commentaires

"Tout peut arriver, n'importe quoi". Undefined ne signifie pas que quoi que ce soit peut arriver. Il y a un ensemble de choses qui peuvent éventuellement se produire lorsque vous lisez en dehors des limites d'un tableau. Votre ordinateur qui se transforme en lapin n'en fait pas partie. :)


@MineR C'est écrire , pas lire. De plus, bien sûr, l'ordinateur ne peut pas commencer à violer les lois de la physique tout d'un coup, mais le fait est que la norme C ne limite pas ce qui pourrait arriver. Vous ne pouvez pas raisonner à ce sujet, à moins de savoir quel code le compilateur a généré pour ce cas, et comment la machine sous-jacente agit lorsque les instructions réelles générées s'exécutent dans ces conditions.


OU PIRE. U.B. Cela signifie qu'il peut fonctionner correctement pendant des décennies, puis échouer, sans aucune raison apparente.



2
votes

Lors de la première itération de la boucle, j = n = 5 . Cependant, vous lisez depuis LA [j] , qui est LA [5] . LA seulement 5 éléments, vous pouvez donc lire et écrire dans LA [0] dans LA [4] . Vous essayez alors d'écrire dans LA [6] , qui est encore plus au-delà des limites du tableau!

Corrigez votre algorithme - vous n'êtes pas autorisé à lire ou à écrire sur des éléments en dehors des limites du tableau.

La raison pour laquelle cela "fonctionne" en C est que C ne vérifie pas si vous lisez ou écrivez en dehors des limites du tableau. Vous lisez en fait une valeur aléatoire qui reste en mémoire au-delà de la fin de votre tableau. Techniquement, cela invoque un comportement indéfini, et tout peut arriver.


0 commentaires

0
votes

Au lieu d'un tableau, vous pouvez insérer facilement un élément en utilisant C # ArrayList ou List comme:

 static void Main(string[] args)
 {
     ArrayList LA = new ArrayList() { 1, 3, 5, 7, 8 };
     Console.WriteLine("The Original array elements are:" + string.Join(",", LA.ToArray()));

     int item = 10, k = 3;
     LA.Insert(k, item);
     Console.WriteLine("The array elements after insertion:" + string.Join(",", LA.ToArray()));

     Console.ReadKey();
 }

Dotnetfiddle: https://dotnetfiddle.net/ISzZPz


9 commentaires

Veuillez ne pas utiliser ArrayList - il était obsolète en C # 2, il y a 13 ans! Utilisez une List générique. Notez également que votre suggestion combinée à son code plante toujours.


Non, ça ne plante pas. Je l'exécute dans une application console et je l'exécute ici.


Comme dans, si vous essayez d'utiliser l'algorithme d'origine de l'OP - LA [j + 1] = LA [j]; etc - cela plantera, car vous faites toujours un hors-limites tableau lu. Votre réponse ignore cela, en jetant l'algorithme d'origine de l'OP et en écrivant autre chose à la place.


Argument très drôle :) pourquoi vous voulez utiliser LA [j + 1] = LA [j]; avec ArrayList. ArrayList a sa propre fonction d'insertion. Quoi qu'il en soit, je me concentre sur la solution de ce problème en utilisant C # et non la sortie. Parce que vous pouvez représenter cette sortie de trop de façons en C #.


@ canton7 Autre chose, pourquoi vous découragez quelqu'un d'utiliser ArrayList . Selon le domaine du problème, si quelqu'un a besoin d'utiliser plusieurs types ensemble comme string et int , dans ce cas, il doit utiliser ArrayList . Parce que vous ne pouvez pas utiliser plusieurs types en utilisant List .


@Arif même dans ce cas, il est recommandé d'utiliser List


@Arif L'OP veut utiliser LA [j + 1] = LA [j]; - c'est dans sa question. L'OP ne veut pas faire d'insertion et rien dans sa question n'indique qu'il veut faire l'insertion.


@ canton7 vous ne pouvez pas comprendre mon point sur les types multiples. En utilisant ArrayList, vous pouvez faire ceci new ArrayList () {1, 3, 5, 7, 8, "canton7", "Arif"}; . Mais vous ne pouvez pas le faire en utilisant List . Dans ce cas, objet / dynamique est très coûteux. Parce que vous avez besoin d'une exécution supplémentaire pour obtenir les données appropriées de objet .


continuons cette discussion dans le chat .