Quelle serait la meilleure façon de déterminer si une chaîne de caractères contient une adresse IPv4 ? Devrais-je utiliser isdigit()
?
Réponses
Trop de publicités?J'ai demandé une question similaire pour le C++ . Vous devriez pouvoir utiliser une version légèrement modifiée (pour le C) de ce que j'avais proposé à l'époque.
bool isValidIpAddress(char *ipAddress)
{
struct sockaddr_in sa;
int result = inet_pton(AF_INET, ipAddress, &(sa.sin_addr));
return result != 0;
}
Vous devez #include <arpa/inet.h>
pour utiliser le inet_pton() fonction.
Mise à jour sur la base des commentaires à la question : Si vous voulez savoir si une chaîne de style C contient une adresse IP, vous devez combiner les deux réponses données jusqu'à présent. Utilisez une expression régulière pour trouver des motifs qui correspondent approximativement à une adresse IP, puis utilisez la fonction ci-dessus pour vérifier la correspondance et voir s'il s'agit d'une vraie adresse.
Il s'agit d'une routine que j'ai écrite il y a quelque temps pour un système embarqué qui générait divers modèles suspects sur un réseau. En tant que telle, elle utilise absolument non des choses fantaisistes comme les bibliothèques réseau ou même les bibliothèques C standard, préférant rester à l'écart de tous les trucs modernes comme la symbolisation des chaînes de caractères et les bibliothèques d'expressions régulières (qui font frémir) :-) A cette fin, il est adapté à presque tous les environnements dans lesquels vous pourriez vous trouver, et il était d'une rapidité aveuglante.
Toutefois, si vous êtes dans un environnement qui a quelque chose comme checkIp4Addess()
Je vous suggère de l'utiliser à la place. Il s'agit d'une indication des problèmes que l'on doit parfois affronter lorsqu'on fait des choses intégrées (bien qu'il s'agisse d'un problème de sécurité). est une véritable solution).
int isValidIp4 (char *str) {
int segs = 0; /* Segment count. */
int chcnt = 0; /* Character count within segment. */
int accum = 0; /* Accumulator for segment. */
/* Catch NULL pointer. */
if (str == NULL)
return 0;
/* Process every character in string. */
while (*str != '\0') {
/* Segment changeover. */
if (*str == '.') {
/* Must have some digits in segment. */
if (chcnt == 0)
return 0;
/* Limit number of segments. */
if (++segs == 4)
return 0;
/* Reset segment values and restart loop. */
chcnt = accum = 0;
str++;
continue;
}
/* Check numeric. */
if ((*str < '0') || (*str > '9'))
return 0;
/* Accumulate and check segment. */
if ((accum = accum * 10 + *str - '0') > 255)
return 0;
/* Advance other segment specific stuff and continue loop. */
chcnt++;
str++;
}
/* Check enough segments and enough characters in last segment. */
if (segs != 3)
return 0;
if (chcnt == 0)
return 0;
/* Address okay. */
return 1;
}
Il fonctionne avec la représentation de l'adresse décimale en pointillés (quatre segments), mais comme c'est de loin la forme la plus courante, je ne considère pas cela comme une limitation. Il y a étaient d'autres représentations il y a longtemps (qui sont probablement encore valables) mais il est rare de les voir.
int validateIP4Dotted(const char *s)
{
int len = strlen(s);
if (len < 7 || len > 15)
return 0;
char tail[16];
tail[0] = 0;
unsigned int d[4];
int c = sscanf(s, "%3u.%3u.%3u.%3u%s", &d[0], &d[1], &d[2], &d[3], tail);
if (c != 4 || tail[0])
return 0;
for (int i = 0; i < 4; i++)
if (d[i] > 255)
return 0;
return 1;
}
J'utiliserais cette expression régulière (avec l'aimable autorisation de Exemples d'expressions régulières ) :
`\b(?:\d{1,3}\.){3}\d{1,3}\b`
Je donnerai la solution "je ne veux pas deux problèmes" :
#include <string.h>
int isIp_v4( char* ip){
int num;
int flag = 1;
int counter=0;
char* p = strtok(ip,".");
while (p && flag ){
num = atoi(p);
if (num>=0 && num<=255 && (counter++<4)){
flag=1;
p=strtok(NULL,".");
}
else{
flag=0;
break;
}
}
return flag && (counter==3);
}
EDIT : strtok peut ne pas être thread safe (crédits à Adam Rosenfield)
- Réponses précédentes
- Plus de réponses