Skip to content

Commit a48e37f

Browse files
committed
Add validate-ip-address
1 parent 35c5bca commit a48e37f

File tree

3 files changed

+181
-0
lines changed

3 files changed

+181
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ add_subdirectory(letter-comb)
55
add_subdirectory(lgc)
66
add_subdirectory(parentheses)
77
add_subdirectory(remove-duplicates-from-sorted)
8+
add_subdirectory(validate-ip)

validate-ip/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
set(CMAKE_C_STANDARD 99)
2+
3+
add_executable(validate-ip main.c)

validate-ip/main.c

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
#include <ctype.h>
2+
#include <stdbool.h>
3+
#include <stdio.h>
4+
#include <string.h>
5+
6+
/**
7+
* Convert a string to an uint8 or return error.
8+
* @note Does not check if input string is made only of valid numbers but checks
9+
* for leading zeros, which are treated as an error.
10+
* @param str Valid number as string.
11+
* @return -1 on error, a num castable to uint8 otherwise.
12+
*/
13+
static int strtou8(const char *str)
14+
{
15+
if (strlen(str) == 0) {
16+
return -1;
17+
}
18+
// no leading zeros are allowed.
19+
if (*str == '0' && *(str + 1) != '\0') {
20+
return -1;
21+
}
22+
23+
char len = (char)strlen(str);
24+
int res = 0;
25+
int pos = 1;
26+
for (int i = 0; i < len - 1; ++i) {
27+
pos *= 10;
28+
}
29+
for (const char *c = str; *c != '\0'; ++c, pos /= 10) {
30+
res += (*c - '0') * pos;
31+
}
32+
if (res < 0 || res > 255) {
33+
return -1;
34+
}
35+
return res;
36+
}
37+
38+
static bool validateIpv4(const char *queryIP)
39+
{
40+
char ip[4][4] = { 0 };
41+
char ip_num_idx = 0;
42+
char ip_num_str_idx = 0;
43+
for (const char *c = queryIP; *c != '\0'; ++c) {
44+
if (*c == '.') {
45+
++ip_num_idx;
46+
ip_num_str_idx = 0;
47+
48+
// too many dots: invalid ipv4
49+
if (ip_num_idx > 3) {
50+
return false;
51+
}
52+
continue;
53+
}
54+
// not a digit other than dots: invalid ipv4
55+
if (!isdigit(*c)) {
56+
return false;
57+
}
58+
59+
// u8 biggest char count is (255): invalid ipv4 otherwise.
60+
if (ip_num_str_idx >= 3) {
61+
return false;
62+
}
63+
64+
ip[ip_num_idx][ip_num_str_idx++] = *c;
65+
}
66+
67+
for (char i = 0; i < 4; ++i) {
68+
if (strtou8(ip[i]) == -1) {
69+
return false;
70+
}
71+
}
72+
return true;
73+
}
74+
75+
static bool isHex(char ch)
76+
{
77+
if (isdigit(ch)) {
78+
return true;
79+
}
80+
81+
switch (ch) {
82+
case 'a':
83+
case 'b':
84+
case 'c':
85+
case 'd':
86+
case 'e':
87+
case 'f':
88+
case 'A':
89+
case 'B':
90+
case 'C':
91+
case 'D':
92+
case 'E':
93+
case 'F':
94+
return true;
95+
default:
96+
return false;
97+
}
98+
}
99+
100+
static bool validateIpv6(const char *queryIP)
101+
{
102+
char ip[8][5] = { 0 };
103+
char ip_num_idx = 0;
104+
char ip_num_str_idx = 0;
105+
for (const char *c = queryIP; *c != '\0'; ++c) {
106+
if (*c == ':') {
107+
++ip_num_idx;
108+
ip_num_str_idx = 0;
109+
110+
// too many dots: invalid ipv6
111+
if (ip_num_idx > 7) {
112+
return false;
113+
}
114+
continue;
115+
}
116+
// not a digit other than dots: invalid ipv4
117+
if (!isHex(*c)) {
118+
return false;
119+
}
120+
121+
// too many chars for num: invalid ipv4 otherwise.
122+
if (ip_num_str_idx >= 4) {
123+
return false;
124+
}
125+
126+
ip[ip_num_idx][ip_num_str_idx++] = *c;
127+
}
128+
129+
for (char i = 0; i < 8; ++i) {
130+
if (strlen(ip[i]) < 1) {
131+
return false;
132+
}
133+
}
134+
return true;
135+
}
136+
137+
char *validIPAddress(char *queryIP)
138+
{
139+
for (char *c = queryIP; *c != '\0'; ++c) {
140+
switch (*c) {
141+
case '.':
142+
if (validateIpv4(queryIP)) {
143+
return "IPv4";
144+
}
145+
return "Neither";
146+
case ':':
147+
if (validateIpv6(queryIP)) {
148+
return "IPv6";
149+
}
150+
return "Neither";
151+
}
152+
}
153+
return "Neither";
154+
}
155+
156+
static void test(const char *ip)
157+
{
158+
printf("ip: %-40s | res: %s\n", ip, validIPAddress(ip));
159+
}
160+
161+
/* https://leetcode.com/problems/validate-ip-address/ */
162+
int main(void)
163+
{
164+
test("1.0.1.");
165+
test("192.168.30.0");
166+
test("192.168.01.1");
167+
test("192.168.01.");
168+
test("0.168.30.1");
169+
test("192.101.30.1");
170+
test("192.1013.30.1");
171+
test("192.101.30.1422");
172+
test("192.101..142");
173+
174+
test("2001:0db8:85a3:0:0:8A2E:0370:7334");
175+
test("2001:0db8:85a3::0:8A2E:0370:7334");
176+
return 0;
177+
}

0 commit comments

Comments
 (0)