Concat 4 entiers en un seul entier

Salut, je suis en train de concatiner 4 nombres entiers un entier. J’ai utilisé la fonction concatinate trouvée ici:

https://stackoverflow.com/a/12700533/2016977

Mon code:

unsigned concatenate(unsigned x, unsigned y) { unsigned pow = 10; while(y >= pow) pow *= 10; return x * pow + y; } void ssortingngtoint(){ struct router *ptr; ptr=start; while(ptr!=NULL){ int a; int b; int c; int d; sscanf(ptr->ip, "%d.%d.%d.%d", &a, &b, &c, &d); int num1 = concatenate(a,b); int num2 = concatenate(c,d); int num3 = concatenate(num1,num2); printf("%d\n",num3); ptr=ptr->next; }; } 

Le problème:

Je traite des numéros d’adresses IP, par exemple 198.32.141.140 je les décompose en 4 entiers et je les concatène pour former 19832141140 . concatène les adresses IP qui sont de petits nombres, par exemple 164.78.104.1 devient 164781041 (ce qui est correct)

Comment dois-je résoudre le problème? En gros, j’essaie de créer une chaîne d’adresses IP, par exemple 198.32.141.140 en un nombre entier 19832141140

Votre approche proposée est probablement une très grosse erreur. Comment distingue-t-on 127.0.1.1 de 127.0.0.11 ?

Il est bien préférable de traiter les adresses IP exactement comme elles sont. À savoir, abcd représente

 a * 256^3 + b * 256^2 + c * 256^1 + d * 256^0 

et fait de cette façon, vous ne pouvez pas éventuellement rencontrer le problème que je viens de décrire. De plus, la mise en œuvre est sortingviale:

 unsigned int number; number = (a << 24) + (b << 16) + (c << 8) + d 

Vous pouvez lire une ligne, puis utiliser inet_aton() . Sinon, vous pouvez faire ce que Jason dit, mais vous devez vérifier chaque valeur entière comprise entre 0 et 255 (ces 4 x 8 bits représentent l’entier 32 bits contenant une adresse IPv4). inet_aton() charge la notation hexadécimale, décimale et octale des adresses IPv4.

 /** ** You DO NOT want to do this usually... **/ #include  uint_fast64_t concatIPv4Addr(uint_fast16_t parts[]) { uint_fast64_t n = 0; for (int i = 0; i < 3; ++i) { n += parts[i]; n *= 1000; } return (n += parts[3]); } 

J'ai utilisé les types entiers "rapides" à des fins de rapidité, mais si vous avez un besoin de stockage, utilisez les types "les moins" correspondants à la place. Bien entendu, cela suppose que vous ayez un compilateur C99 ou un compilateur C89 avec des extensions. Sinon, vous êtes coincé avec les types primitifs où un caractère pourrait même être 32 bits selon le standard C. Comme je ne connais pas votre environnement cible, je n’ai fait aucune hypothèse. N'hésitez pas à changer pour les types primitifs appropriés comme bon vous semble.

J'ai utilisé une valeur de 16 bits (minimum), car un nombre de 8 bits ne peut représenter que 0 à 255, ce qui signifie que si 358 était entré accidentellement, il serait interprété comme 102, ce qui est toujours valide. Si vous avez un type capable de stocker plus de 8 bits et moins de 16 bits, vous pouvez évidemment l'utiliser, mais le type doit pouvoir stocker plus de 8 bits.

Cela dit, vous aurez besoin d'au moins un type 38 bits:

 4294967295 (32-bit unsigned max) 255255255255 (255.255.255.255 converted to the integer you want) 274877906944 (38-bit unsigned max) 

La fonction ci-dessus convertira respectivement 127.0.1.1 et 127.0.0.11 en 127000001001 et 127000000011:

 127.0.1.1 -> 127.000.001.001 -> 127000001001 127.0.0.11 -> 127.000.000.011 -> 127000000011 

Pourquoi tant de zéros? Parce que sinon vous ne pouvez pas faire la différence entre eux! Comme d'autres l'ont dit, vous pourriez confondre 127.0.1.1 et 127.0.0.11. En utilisant la fonction ci-dessus ou quelque chose de plus approprié qui convertit une adresse IPv4 en sa représentation décimale réelle, vous n'aurez pas un tel problème.

Enfin, je n’ai pas validé l’adresse IPv4 transmise à la fonction. Je suppose que vous vous assurez déjà que l'adresse est valide avant d'appeler des fonctions qui sauvegardent ou utilisent l'adresse IPv4. En passant, si vous vouliez faire la même chose pour IPv6, vous ne pouvez pas le faire facilement, car cela nécessiterait une chaîne ou une conversion en décimal de chacune des 8 parties, chacune ayant au plus 16 bits, donnant 5 chiffres décimaux. par partie ou 40 chiffres. Pour stocker cela, vous avez besoin d'un minimum de 133 bits, plutôt que des 128 bits requirejs pour l'adresse IPv6, tout comme vous auriez besoin de 38 bits pour stocker une adresse IPv4 au lieu des 32 bits requirejs.

Toujours pas trop mal, non? Qu'en est-il d'un IPv8 théorique comportant 16 parties, chacune ayant une taille de 32 bits? La fonction équivalente à celle ci-dessus nécessiterait 580 bits, au lieu de l'exigence mathématique appropriée: 512 bits. Bien que cela ne pose pas de problème aujourd'hui, je signale simplement l'erreur de ne rien faire avec une adresse IPv4 représentée par la concaténation des valeurs décimales de chaque partie. Ça pèse absolument terriblement.