Optimisation pour une comparaison de chaîne en c/c++

Optimisation pour une comparaison de chaîne en c/c++ - Programmation

Marsh Posté le 15-03-2002 à 13:05:36    

Voilà mon programme doit entre autre comparer un nombre important d'entrées et à la base ce sont des chaînes de caractères de cette forme : "   192.168.10.1", "    10.12.12.12", "172.195.120.230".
La chaine est de taille fixe et les données (IP) sont séparées par un point.
 
Je dois déterminer vers quel réseau elle vont donc il faut que j'examine les deux premiers chiffres puis le troisième.
J'ai parcouru la chaine et converti les bouts de chaine en entiers pour ensuite faire la comparaison.
 
Mais ce serait il pas plus rapide si j'arrivai à chopper avec une commande les deux premiers chiffres, transformation avec atoi qui me donnerai par exemple "163.104" -> 163.104 et ensuite je choppe le troisième chiffre.
 
Bon je suis pas sur de la deuxième solution mais si qn à une idée je suis preneur.

Reply

Marsh Posté le 15-03-2002 à 13:05:36   

Reply

Marsh Posté le 15-03-2002 à 13:16:37    

Yo mec,
 
  C'est bien beau ton truc, mais on y comprends quedalle...
 
Menfin, c'est du C, pis c'est bien chiant comme truc....
Allez bon courage............
 
                                     JOEY :gun:

Reply

Marsh Posté le 15-03-2002 à 13:21:16    

oh lala joey joe..  
pourtant, tu es hyper fort en c...
 
:hello: :gun:

Reply

Marsh Posté le 15-03-2002 à 13:21:34    

:hello:gun:

Reply

Marsh Posté le 15-03-2002 à 13:21:50    

:hello::gun:

Reply

Marsh Posté le 15-03-2002 à 13:31:14    

Je pense que ce qu'il "faut", c'est d'abord récupérer le premier NOMBRE 192 (constitué de 3 chiffres 1 9 2), puis le second puis le troisième.
 
atoi() sur 163.104 ne donnera guère "163.104" car les entiers n'ont pas de virgule (.).
 
En cherchant le point séparateur jusqu'à atteindre le champ voulu, c'est peut être le plus "naturel".
 
Si le but est de comparer "en bloc", y a moyen de formater à trois digits (000 à 999) chaque nombre de 10.12.12 en 010012012 après avoir récupéré le 10, le 12 et le 12. Pour comparer au 192168010... Tout dépend du but.
 
Le plus rapide, ça dépend de comment c'est "optimisé", et du traitement.

Reply

Marsh Posté le 15-03-2002 à 13:31:30    

Bon je recommence si cétait pas clair :  
Analyse de chaine de caractères de 14 caractères de types :  
"192.168.254.213"
" 192.168.12.213"
"  192.168.12.12"
"     10.10.10.1"
 
Les données qui me permettent d'analyser vers ou vont ces adresses sont les deux premiers chiffres qui me donnent le groupe de batiment de destination. Le troisième chiffre me donne le batiment exact.
Je dois tout d'abord analyser les deux premiers chiffres des adresses pour déterminer si la destination des adresses est internet et dans ce cas je m'en fou du reste. Si la destination n'est pas internet alors faut que je regarde le troisième chiffre pour savoir ou ca va exactement.
 
Pour le moment je parcourt la liste et je transforme chacun des "chiffres chaîne de caractères" en entier et ensuite je fais mes comparaisons.
 
Mais si qqn à une idée plus rapide je suis preneur parce que des adresses comme ca j'en ai des tonnes à analyser.
 
(j'éspère que c plus clair)

Reply

Marsh Posté le 15-03-2002 à 13:48:14    

Pour être plus précis, les chiffres analysés sont le 1 et le 9 du nombre 192, puis le 2 si le 1 et le 9 sont en "interne".
 
Le nombre 10 est considéré comme 010. Donc chiffres 0 et 1 et 0.

Reply

Marsh Posté le 15-03-2002 à 14:04:52    

sorry mais po fort compris ta comparaison je suis entrain de faire un optimisation mais je suis coince car pas fort compris !!!

Reply

Marsh Posté le 15-03-2002 à 14:06:12    

que veux tu dire par 1ere 2eme et 3 eme chiffre ?

Reply

Marsh Posté le 15-03-2002 à 14:06:12   

Reply

Marsh Posté le 15-03-2002 à 14:21:18    

J'ai l'impression qu'il confusionne les chiffres (char) et les nombres (formés de chiffres). ???

Reply

Marsh Posté le 15-03-2002 à 14:35:20    

J'pense que le meilleur moyen, c effectivement d'extraire ts les chiffres dans une structure, et de comparer après.
Perso, j'ferai un truc comme ça (g pas essayé non plus, ms bon):
 
dans ton .h:
 

Code :
  1. typedef struct _IP_ADRESS
  2. {
  3.    long m_lgOctet1;
  4.    long m_lgOctet2;
  5.    long m_lgOctet3;
  6.    long m_lgOctet4;
  7. } IPADRESS;
  8. typedef IPADRESS * LPIPADRESS;  // type Pointeur, pas utlilisé ici, mais souvent utile.


 
et dans ton .cpp:
 

Code :
  1. char szFullAdress[] = "192.168.10.1"  // par exemple
  2. IPADRESS AdresseIp;
  3. memet (&AdresseIp, 0, sizeof (IPADRESS));
  4. sscanf (szFullAdress, "%ld.%ld.%ld.%ld", AdresseIp.m_lgOctet1, AdresseIp.m_lgOctet2,AdresseIp.m_lgOctet3, AdresseIp.m_lgOctet4);


 
Et après, ta structure est remplie.
le sscanf, ça peut être vachement pratique, et c pas très très connu. (ça reste à tester qd même mon truc, je suis pas sur à 100%)

 

[jfdsdjhfuetppo]--Message édité par El_Gringo--[/jfdsdjhfuetppo]

Reply

Marsh Posté le 15-03-2002 à 16:23:26    

Par 1er 2ème et 3ème je veux parler des nombres de l'adresse IP, une adresse IP est découpée en 4 nombres.
 
Gringo : comment ca marche du tonnere le sscanf, grand merci.

 

[jfdsdjhfuetppo]--Message édité par merou91--[/jfdsdjhfuetppo]

Reply

Marsh Posté le 15-03-2002 à 16:32:48    

merou91 a écrit a écrit :

Par 1er 2ème et 3ème je veux parler des nombres de l'adresse IP, une adresse IP est découpée en 4 nombres.




 
Alors dit Octet à la place de nombre, tu sera mieux compris.
Octet, parce que, chaque "nombre de l'adresse ip" dont du parle, va de 0 à 255, parce que c'est 1 octet (8 bits).
 

merou91 a écrit a écrit :

 
Gringo : comment ca marche du tonnere le sscanf, grand merci.  




 
Ouais, c bien comme truc, hein !? :sol:

Reply

Marsh Posté le 15-03-2002 à 16:37:02    

ElGringo, le ElGringo du clan MAD ?

Reply

Marsh Posté le 15-03-2002 à 18:20:13    

Au hasard,
 

Citation :

#include <arpa/inet.h>  
in_addr_t inet_addr(const char *cp);  
The inet_addr() function converts the specified string, in the Internet standard dot notation, to an integer value suitable for use as an Internet address.  
The converted address is in network byte order (bytes ordered from left to right).


 

Citation :

The inet_addr function converts a string containing an (Ipv4) Internet Protocol dotted address into a proper address for the IN_ADDR structure.
 
unsigned long inet_addr(
  const char   FAR *cp  
);
 
Requirements:
  Windows NT/2000/XP: Included in Windows NT 3.1 and later.
  Windows 95/98/Me: Included in Windows 95 and later.
  Header: Declared in Winsock2.h.
  Library: Use Ws2_32.lib.


 
Sinon pour le fun, un truc qui prend deux minutes
a ecrire:
 

Code :
  1. struct addr_t{
  2.     BYTE m_Octet1;
  3.     BYTE m_Octet2;
  4.     BYTE m_Octet3;
  5.     BYTE m_Octet4;
  6. };
  7. int strtoip(char *IPCHAIN, addr_t &IPADDRESS)
  8. {
  9.   char *ITERATEUR = IPCHAIN;
  10.   char c = *ITERATEUR;
  11.  
  12.   memset (&IPADDRESS, 0, sizeof(addr_t));
  13.  
  14.   trim:
  15.     // on ignore les espaces
  16.     switch (c) {
  17.       case ' ':
  18.      ++ITERATEUR;
  19.      c = *ITERATEUR;
  20.      goto trim;
  21.       case '\0':
  22.         goto erreur;
  23.       default:
  24.      goto octet1;
  25.     }
  26.   octet1:
  27.     // On calcule le premier octet
  28.     switch (c) {
  29.       case '.':
  30.      ++ITERATEUR;
  31.      c = *ITERATEUR;
  32.        goto octet2;
  33.       case '\0':
  34.         goto erreur;
  35.       default:
  36.         // on suppose que la chaine est correcte !!
  37.         IPADDRESS.m_Octet1 *= 10;
  38.         IPADDRESS.m_Octet1 += c - '0';
  39.      ++ITERATEUR;
  40.      c = *ITERATEUR;
  41.      goto octet1;
  42.     }
  43.   octet2:
  44.     // On calcule le deuxieme octet
  45.     switch (c) {
  46.       case '.':
  47.      ++ITERATEUR;
  48.      c = *ITERATEUR;
  49.        goto octet3;
  50.       case '\0':
  51.         goto erreur;
  52.       default:
  53.         // on suppose que la chaine est correcte !!
  54.         IPADDRESS.m_Octet2 *= 10;
  55.         IPADDRESS.m_Octet2 += c - '0';
  56.      ++ITERATEUR;
  57.      c = *ITERATEUR;
  58.      goto octet2;
  59.     }
  60.   octet3:
  61.     // On calcule le troisieme octet
  62.     switch (c) {
  63.       case '.':
  64.      ++ITERATEUR;
  65.      c = *ITERATEUR;
  66.        goto octet4;
  67.       case '\0':
  68.         goto erreur;
  69.       default:
  70.         // on suppose que la chaine est correcte !!
  71.         IPADDRESS.m_Octet3 *= 10;
  72.         IPADDRESS.m_Octet3 += c - '0';
  73.      ++ITERATEUR;
  74.      c = *ITERATEUR;
  75.      goto octet3;
  76.     }
  77.   octet4:
  78.     // On calcule le quatrieme octet
  79.     switch (c) {
  80.       case '.':
  81.        goto erreur;
  82.       case '\0':
  83.         goto fin;
  84.       default:
  85.         // on suppose que la chaine est correcte !!
  86.         IPADDRESS.m_Octet4 *= 10;
  87.         IPADDRESS.m_Octet4 += c - '0';
  88.      ++ITERATEUR;
  89.      c = *ITERATEUR;
  90.      goto octet4;
  91.     }
  92.   erreur:
  93.    // On traite l'erreur
  94.    return -1;
  95.   fin: 
  96.    // Fin
  97.    return 0;
  98. }


 
disclaimer: Code garanti non teste donné "as is",Attention ne faites pas la meme chose  
a la maison.  
 
A+
LEGREG

Reply

Marsh Posté le 15-03-2002 à 18:23:37    

legreg a écrit a écrit :

Au hasard,
 

Citation :

#include <arpa/inet.h>  
in_addr_t inet_addr(const char *cp);  
The inet_addr() function converts the specified string, in the Internet standard dot notation, to an integer value suitable for use as an Internet address.  
The converted address is in network byte order (bytes ordered from left to right).


 

Citation :

The inet_addr function converts a string containing an (Ipv4) Internet Protocol dotted address into a proper address for the IN_ADDR structure.
 
unsigned long inet_addr(
  const char   FAR *cp  
);
 
Requirements:
  Windows NT/2000/XP: Included in Windows NT 3.1 and later.
  Windows 95/98/Me: Included in Windows 95 and later.
  Header: Declared in Winsock2.h.
  Library: Use Ws2_32.lib.


 
Sinon pour le fun, un truc qui prend deux minutes
a ecrire:
 

Code :
  1. struct addr_t{
  2.     BYTE m_Octet1;
  3.     BYTE m_Octet2;
  4.     BYTE m_Octet3;
  5.     BYTE m_Octet4;
  6. };
  7. int strtoip(char *IPCHAIN, addr_t &IPADDRESS)
  8. {
  9.   char *ITERATEUR = IPCHAIN;
  10.   char c = *ITERATEUR;
  11.  
  12.   memset (&IPADDRESS, 0, sizeof(addr_t));
  13.  
  14.   trim:
  15.     // on ignore les espaces
  16.     switch (c) {
  17.       case ' ':
  18.      ++ITERATEUR;
  19.      c = *ITERATEUR;
  20.      goto trim;
  21.       case '\0':
  22.         goto erreur;
  23.       default:
  24.      goto octet1;
  25.     }
  26.   octet1:
  27.     // On calcule le premier octet
  28.     switch (c) {
  29.       case '.':
  30.      ++ITERATEUR;
  31.      c = *ITERATEUR;
  32.        goto octet2;
  33.       case '\0':
  34.         goto erreur;
  35.       default:
  36.         // on suppose que la chaine est correcte !!
  37.         IPADDRESS.m_Octet1 *= 10;
  38.         IPADDRESS.m_Octet1 += c - '0';
  39.      ++ITERATEUR;
  40.      c = *ITERATEUR;
  41.      goto octet1;
  42.     }
  43.   octet2:
  44.     // On calcule le deuxieme octet
  45.     switch (c) {
  46.       case '.':
  47.      ++ITERATEUR;
  48.      c = *ITERATEUR;
  49.        goto octet3;
  50.       case '\0':
  51.         goto erreur;
  52.       default:
  53.         // on suppose que la chaine est correcte !!
  54.         IPADDRESS.m_Octet2 *= 10;
  55.         IPADDRESS.m_Octet2 += c - '0';
  56.      ++ITERATEUR;
  57.      c = *ITERATEUR;
  58.      goto octet2;
  59.     }
  60.   octet3:
  61.     // On calcule le troisieme octet
  62.     switch (c) {
  63.       case '.':
  64.      ++ITERATEUR;
  65.      c = *ITERATEUR;
  66.        goto octet4;
  67.       case '\0':
  68.         goto erreur;
  69.       default:
  70.         // on suppose que la chaine est correcte !!
  71.         IPADDRESS.m_Octet3 *= 10;
  72.         IPADDRESS.m_Octet3 += c - '0';
  73.      ++ITERATEUR;
  74.      c = *ITERATEUR;
  75.      goto octet3;
  76.     }
  77.   octet4:
  78.     // On calcule le quatrieme octet
  79.     switch (c) {
  80.       case '.':
  81.        goto erreur;
  82.       case '\0':
  83.         goto fin;
  84.       default:
  85.         // on suppose que la chaine est correcte !!
  86.         IPADDRESS.m_Octet4 *= 10;
  87.         IPADDRESS.m_Octet4 += c - '0';
  88.      ++ITERATEUR;
  89.      c = *ITERATEUR;
  90.      goto octet4;
  91.     }
  92.   erreur:
  93.    // On traite l'erreur
  94.    return -1;
  95.   fin: 
  96.    // Fin
  97.    return 0;
  98. }


 
disclaimer: Code garanti non teste donné "as is",Attention ne faites pas la meme chose  
a la maison.  
 
A+
LEGREG  




C'est bien lourd comme codage pour un truc aussi simple..

Reply

Marsh Posté le 15-03-2002 à 18:27:53    

*Syl* a écrit a écrit :

 
C'est bien lourd comme codage pour un truc aussi simple..  




 
et bien s'il ne veut pas utiliser les fonctions
de librairie qui font le boulot.. :D
 
LEGREG

Reply

Marsh Posté le 16-03-2002 à 13:35:31    

merou91 a écrit a écrit :

Bon je recommence si cétait pas clair :  
Analyse de chaine de caractères de 14 caractères de types :  
"192.168.254.213"
" 192.168.12.213"
"  192.168.12.12"
"     10.10.10.1"
 
Les données qui me permettent d'analyser vers ou vont ces adresses sont les deux premiers chiffres qui me donnent le groupe de batiment de destination. Le troisième chiffre me donne le batiment exact.
Je dois tout d'abord analyser les deux premiers chiffres des adresses pour déterminer si la destination des adresses est internet et dans ce cas je m'en fou du reste. Si la destination n'est pas internet alors faut que je regarde le troisième chiffre pour savoir ou ca va exactement.
 
Pour le moment je parcourt la liste et je transforme chacun des "chiffres chaîne de caractères" en entier et ensuite je fais mes comparaisons.
 
Mais si qqn à une idée plus rapide je suis preneur parce que des adresses comme ca j'en ai des tonnes à analyser.
 
(j'éspère que c plus clair)  




 
 
j'ai une question as tu beaucoup de groupe de batiment ? et de batiment ?
Si il n'y en a pas beaucoup pourquoi ne pas faire ta comparaison dans le sens inverse !!!
Je m'explique si tu as beaucoup d'adresse a analiser ta conversion va s'executer un grand nombre de fois.
 
Maintenant si tu as beaucoup moins de reference a comparer pourquoi ne pas convertir tes adresse de reference en chaine de caractere et tu fais une comparaison sur les caracteres du debut jusqu'au seconde point (pour les groupes de batiments) puis du second point au troisieme(pour les batiments)

Reply

Marsh Posté le 16-03-2002 à 16:09:09    

Bon toutes ces fonctions ont déjà été codées... Un petit coup d'oeil sur le net et t'auras le nom de la librairie avec les fonctions qui vont bien...


---------------
Guerre Dollar - Euro : la chute economique des Etats-Unis avant 2010.
Reply

Marsh Posté le 16-03-2002 à 16:19:11    

zeux a écrit a écrit :

Bon toutes ces fonctions ont déjà été codées... Un petit coup d'oeil sur le net et t'auras le nom de la librairie avec les fonctions qui vont bien...  




je poste pour du beurre??
 
LEGREG

Reply

Marsh Posté le 16-03-2002 à 16:30:18    

legreg a écrit a écrit :

 
je poste pour du beurre??
 
LEGREG  




sorry j'avais tout po lu. :hello:


---------------
Guerre Dollar - Euro : la chute economique des Etats-Unis avant 2010.
Reply

Marsh Posté le 17-03-2002 à 12:33:26    

faire ca en c++ :ouch: ?!
code en 4 minutes chrono
... et verifie sur mon syteme, c encore tout chaud ...
Powered by Perl :D
 
#!/usr/bin/perl
 
@tableau_ip = ("192.168.12.23","10.20.12.23" );
foreach $ip (@tableau_ip)
{
 if ($ip =~ /(\d+)\.(\d+)\.(\d+)\.(\d+)/)  
 {
  $temp =$1.$2;
  if ($temp == "192168" )  
  {
   print "Adresse interne !\n";
  }
  else
  {
   print "coucou :D\n";
   # je fais ce que je veux avec les variable $1,$2, ... recuperee
   # classement destination etc
  };
 }  
 else  
 {
  die("L'ip doit etre du format : nbr.nbr.nbr.nnr, merci !" );
 };
};

Reply

Marsh Posté le 17-03-2002 à 12:41:38    

le monsieur veut pas une version pearl, mais une C++
 
Paske sinon je lui refile une version prolog !  
......
quoique, non, en fait :D

Reply

Marsh Posté le 17-03-2002 à 12:46:29    

bah ... il inclut le code perl dans le code C ou inversement.
une version prolog, euh c quoi ca ? (j'imagine que ca doit etre barbare :D )

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed