What would be a good way to determine if a string contains an IPv4 address? Should I use isdigit()
?
I asked a similar question for C++. You should be able to use a slightly modified (for C) version of what I came up with back then.
bool isValidIpAddress(char *ipAddress)
{
struct sockaddr_in sa;
int result = inet_pton(AF_INET, ipAddress, &(sa.sin_addr));
return result != 0;
}
You'll need to #include <arpa/inet.h>
to use the inet_pton() function.
Update based on comments to the question: If you want to know if a C-style string contains an IP address, then you should combine the two answers given so far. Use a regular expression to find patterns that roughly match an IP address, then use the function above to check the match to see if it's the real deal.
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;
}
I would use this regular expression (courtesy of Regular Expression Examples):
`\b(?:\d{1,3}\.){3}\d{1,3}\b`
I think below C code snippet should work
bool validate_ip4(const char* buffer)
{
if (NULL == buffer) return false;
register const char* pos = buffer;
register unsigned char ch = *pos;
register unsigned short count = 0;
while (ch != NULL)
{
if (!((ch >= '0' && ch <= '9') || ch == '.')) return false;
if (ch == '.')
if (++count > 3) return false;
ch = *++pos;
}
if (count == 3 && *--pos != '.') return true;
return false;
}
This is a routine I wrote a while ago for an embedded system which generated various suspect patterns on a network. As such, it uses absolutely no fancy stuff like network libraries or even the standard C libraries, preferring to steer clear of all that modern stuff like string tokenizing and (shudder) regular expression libraries :-) To that end, it's suited to just about any environment you could find yourself in, and it was blindingly fast.
Although, if you're in an environment that has something like checkIp4Addess()
, I'd suggest you use that instead. It's an indication of the stuff you sometimes have to put up with when doing embedded stuff (although it is a real 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;
}
inet_addr() is much better than inet_aton() for number-and-dot notation representation IPv4 IP address checking.