[Classic Interview Questions] Please use C language programming to judge the legality of IPV4 addresses

C language programming to realize the legality judgment of IPV4 address

Friends who have known me may have some impressions. I wrote about this topic in my blog N years ago. At that time, I really encountered this problem at work. I thought that after the work was finished, I would add the code to solve this problem, but it turned out to be a pigeon for several years. I am really ashamed. Now this part of the code is made public, everyone is welcome to download and test.

1 written in front

Friends who have known me may have some impressions. I wrote about this topic in my blog N years ago. At that time, I really encountered this problem at work. I thought that after the work was finished, I would add the code to solve this problem, but it turned out to be a pigeon for several years. I am really ashamed. Now this part of the code is made public, everyone is welcome to download and test.

If you find a problem with the code, please contact me by private message.

2 Demand Analysis

In fact, the requirement of this topic is very simple, that is, input a string and judge whether it is a legal IPv4 address. Just from the function point of view, it seems very simple, but it needs some effort to make it perfect. If you don't believe me, take a look at the disassembly below.

Image result for IPV4

3 simple version

Let's start with a simple version and look directly at the code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int is_valid_ipv4(const char *ip_address) 
{
    
    
    int num, dots = 0;
    char *ptr;

    if (ip_address == NULL) {
    
    
        return 0;
    }

    ptr = strtok((char *)ip_address, ".");
    if (ptr == NULL) {
    
    
        return 0;
    }

    while (ptr) {
    
    
        if (!isdigit(*ptr)) {
    
    
            return 0;
        }

        num = atoi(ptr);
        if (num < 0 || num > 255) {
    
    
            return 0;
        }

        ptr = strtok(NULL, ".");
        if (ptr != NULL) {
    
    
            dots++;
        }
    }

    if (dots != 3) {
    
    
        return 0;
    }

    return 1;
}

int check_is_valid_ipv4(const char *ip)
{
    
    
    int ret = 0;
    
    ret = is_valid_ipv4(ip); 

    return ret; 
}

int main(int argc, const char *argv[])
{
    
    
    const char *ip = argv[1];

    printf("check %s\n", ip);
    printf("ret %d\n", check_is_valid_ipv4(ip));
}

Compile and run it. It is no problem to input a common ipv4 address, such as "192.168.0.1"; at the same time, an error will be reported if an illegal character is input.

~/ipv4]$gcc -o test ipv4.c 
~/ipv4]$./test 192.168.0.1
check 192.168.0.1
ret 1
~/ipv4]$./test 
check 192.168.w.2
ret 0

However, if I add a restriction: how to judge that an IPV4 address is a legal host address ?

For example, this: "238.171.84.41", its judgment is still legal, but in fact this is not a legal host address .

~/ipv4]$./test 238.171.84.41
check 238.171.84.41
ret 1

Another one, the above code is not detected, such input: "0192.168.1.1"

~/ipv4]$./test 0192.168.1.1
check 0192.168.1.1
ret 1

So, we need to optimize it.

4 Advanced

As analyzed above, we need to optimize the code:

First of all, it must be judged that the number fields separated by "." cannot start with the "0" character.

    while (ptr) {
    
    
        if (!isdigit(*ptr)) {
    
    
            return 0;
        }

        if (*ptr == '0') {
    
     //check start with '0'
            return 0;
        }

        num = atoi(ptr);
        if (num < 0 || num > 255) {
    
    
            return 0;
        }

        ptr = strtok(NULL, ".");
        if (ptr != NULL) {
    
    
            dots++;
        }
    }

~/ipv4]$./test 0192.168.1.1
check 0192.168.1.1
ret 0

According to the classification of IPv4 addresses:

  • Class A: (1.0.0.1-126.255.255.254) (default subnet mask: 255.0.0.0 or 0xFF000000) The first byte is the network number, and the last three bytes are the host number, expressed as network – host – host – Host. The first part of this type of IP address is "0", so the network number of the address ranges from 1 to 126. There are 16777214 host addresses in total, which are generally used in large networks.

  • Type B: (128.1.0.1-191.254.255.254) (default subnet mask: 255.255.0.0 or 0xFFFF0000) The first two bytes are the network number, and the last two bytes are the host number. The first part of this type of IP address is "10", so the network number of the address ranges from 128 to 191. There are 65534 host addresses in total, which are generally used in medium-sized networks.

  • Type C: (192.0.1.1-223.255.254.254) (subnet mask: 255.255.255.0 or 0xFFFFFF00) The first three bytes are the network number, and the last byte is the host number. The first part of this type of IP address is "110", so the network number of the address ranges from 192 to 223. There are 254 host addresses in total, which are generally used in small networks.

  • Class D: It is a multicast address. (224.0.0.1-239.255.255.254) The first 4 digits of this type of IP address are "1110", so the network number ranges from 224 to 239; the last 28 digits are the multicast address ID. This is a specially reserved address. It does not point to a specific network. Currently, this type of address is used in Multicasting. A multicast address is used to address a group of computers at once, and it identifies a group of computers that share the same protocol.

  • Class E: It is a reserved address, reserved for future use. (240.0.0.0—255.255.255.254) The first part of this type of IP address is "1111", so the value of the network number is between 240~255.

It can be seen that if a normal IPv4 host address is to be met, it can only be of type A, B, or C, but not of type D, or E.

Therefore, when judging, we should increase the category judgment of IPv4 addresses.

Before the above judgment returns, add a judgment:

	if (atoi(ip_address) >= 1 && atoi(ip_address) <= 126) {
    
    
        printf("This is a Class A IP address.\n");
        return 1;
    } else if (atoi(ip_address) >= 128 && atoi(ip_address) <= 191) {
    
    
        printf("This is a Class B IP address.\n");
        return 1;
    } else if (atoi(ip_address) >= 192 && atoi(ip_address) <= 223) {
    
    
        printf("This is a Class C IP address.\n");
        return 1;
    } else {
    
    
        printf("This is not a Class A, B, or C IP address.\n");
        return 0;
    }

The complete code is as follows:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int is_valid_ipv4(const char *ip_address) 
{
    
    
    int num, dots = 0;
    char *ptr;

    if (ip_address == NULL) {
    
    
        return 0;
    }

    ptr = strtok((char *)ip_address, ".");
    if (ptr == NULL) {
    
    
        return 0;
    }

    while (ptr) {
    
    
        if (!isdigit(*ptr)) {
    
    
            return 0;
        }

        if (*ptr == '0') {
    
     //check start '0'
            return 0;
        }

        num = atoi(ptr);
        if (num < 0 || num > 255) {
    
    
            return 0;
        }

        ptr = strtok(NULL, ".");
        if (ptr != NULL) {
    
    
            dots++;
        }
    }

    if (dots != 3) {
    
    
        return 0;
    }

    if (atoi(ip_address) >= 1 && atoi(ip_address) <= 126) {
    
    
        printf("This is a Class A IP address.\n");
        return 1;
    } else if (atoi(ip_address) >= 128 && atoi(ip_address) <= 191) {
    
    
        printf("This is a Class B IP address.\n");
        return 1;
    } else if (atoi(ip_address) >= 192 && atoi(ip_address) <= 223) {
    
    
        printf("This is a Class C IP address.\n");
        return 1;
    } else {
    
    
        printf("This is not a Class A, B, or C IP address.\n");
        return 0;
    }

    return 1;
}

int check_is_valid_ipv4(const char *ip)
{
    
    
    int ret = 0;
    
    ret = is_valid_ipv4(ip); 

    return ret; 
}

int main(int argc, const char *argv[])
{
    
    
    const char *ip = argv[1];

    printf("check %s\n", ip);
    printf("ret %d\n", check_is_valid_ipv4(ip));
}

At this time, let's try the previous non-A/B/C IPv4 address:

~/ipv4]$./test 238.171.84.41
check 238.171.84.41
This is not a Class A, B, or C IP address.
ret 0

~/ipv4]$./test 192.168.2.3
check 192.168.2.3
This is a Class C IP address.
ret 1

So far, a relatively perfect judgment has been basically obtained, but are there any loopholes? Leave it to the reader to figure it out for themselves.

5 advanced version

Experienced programs will definitely find that the above judgments are really troublesome!

Every case needs to compare and judge in this way, how laborious it is!

Is there a more refreshing high-level method?

Of course the answer is yes, at this time you need to understand: regular expressions .

Many mainstream programming languages ​​have standard libraries to support regular expressions, so is there any in C language?

In fact, regular expressions can also be used in the C language. Let’s leave this one in suspense, and let’s listen to the next chapter to break it down.

Welcome to the preview under: Regular Expression Language - Quick Reference | Microsoft Learn

6 Complete Test Cases

This section will add various test cases for you, hoping to help you test the code:

合法的测试输入
192.168.0.1
10.0.0.1
172.16.0.1
255.255.255.255

非法的测试输入
256.0.0.1
192.168.0.0.1
192.168.0
192.168.0.1.2

非法的测试输入
256.0.0.1
192.168.0.0.1
192.168.0
192.168.0.1.2
300.300.300.300
1.2.3
1.2.3.4.5
1.2.3.4.
.1.2.3.4
1..2.3.4

The test cases are constantly enriched, and everyone is welcome to add them.

Guess you like

Origin blog.csdn.net/szullc/article/details/130493657