【面接の定番質問】C言語プログラミングでIPV4アドレスの正当性を判断してください

IPV4アドレスの正当性判定を実現するC言語プログラミング

私のことを知っている友人なら、印象に残っているかもしれませんが、N年前にブログでこの話題を書きました. 作業が終わったら、この問題を解決するコードを追加しようと思っていましたが、数年間ハトでした。現在、コードのこの部分が公開されており、誰でもダウンロードしてテストできます。

1 前に書いた

私のことを知っている友人なら、印象に残っているかもしれませんが、N年前にブログでこの話題を書きました. 作業が終わったら、この問題を解決するコードを追加しようと思っていましたが、数年間ハトでした。現在、コードのこの部分が公開されており、誰でもダウンロードしてテストできます。

コードに問題がある場合は、プライベート メッセージでご連絡ください。

2 需要分析

実際、このトピックの要件は非常に単純です。つまり、文字列を入力して、それが正当な IPv4 アドレスかどうかを判断します。機能の観点から見ると、非常にシンプルに見えますが、完璧にするには多少の努力が必要です。信じられない場合は、以下の分解をご覧ください。

IPV4 の画像結果

3 シンプルバージョン

簡単なバージョンから始めて、コードを直接見てみましょう。

#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));
}

コンパイルして実行すると、「192.168.0.1」などの一般的な ipv4 アドレスを入力しても問題ありませんが、不正な文字を入力するとエラーが報告されます。

~/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

ただし、制限を追加すると、IPV4アドレスが正当なホスト?

たとえば、これは「238.171.84.41」であり、その判断はまだ正当ですが、実際にはこれは正当なホスト

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

もう 1 つ、上記のコードが検出されない場合、「0192.168.1.1」と入力します。

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

したがって、最適化する必要があります。

4 上級

上記で分析したように、コードを最適化する必要があります。

まず、「.」で区切られた数値フィールドが「0」文字で始まることはできないと判断する必要があります。

    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

IPv4 アドレスの分類によると、次のようになります。

  • クラス A: (1.0.0.1-126.255.255.254) (デフォルトのサブネット マスク: 255.0.0.0 または 0xFF000000) 最初のバイトはネットワーク番号で、最後の 3 バイトはホスト番号で、ネットワーク – ホスト – ホスト – ホストとして表されます。 . このタイプの IP アドレスの最初の部分は「0」であるため、アドレスのネットワーク番号は 1 から 126 の範囲です。合計で 16777214 個のホスト アドレスがあり、一般に大規模なネットワークで使用されます。

  • タイプ B: (128.1.0.1-191.254.255.254) (デフォルトのサブネット マスク: 255.255.0.0 または 0xFFFF0000) 最初の 2 バイトはネットワーク番号で、最後の 2 バイトはホスト番号です。このタイプの IP アドレスの最初の部分は「10」であるため、アドレスのネットワーク番号は 128 から 191 の範囲です。合計で 65534 個のホスト アドレスがあり、一般的に中規模のネットワークで使用されます。

  • タイプ C: (192.0.1.1-223.255.254.254) (サブネットマスク: 255.255.255.0 または 0xFFFFFF00) 最初の 3 バイトはネットワーク番号で、最後のバイトはホスト番号です。このタイプの IP アドレスの最初の部分は「110」であるため、アドレスのネットワーク番号は 192 から 223 の範囲になります。合計 254 個のホスト アドレスがあり、一般に小規模なネットワークで使用されます。

  • クラス D: マルチキャスト アドレスです。(224.0.0.1-239.255.255.254) このタイプの IP アドレスの最初の 4 桁は「1110」であるため、ネットワーク番号の範囲は 224 から 239 で、最後の 28 桁はマルチキャスト アドレス ID です。これは特別に予約されたアドレスです。特定のネットワークを指すものではなく、現在、このタイプのアドレスはマルチキャストで使用されています。マルチキャスト アドレスは、コンピュータのグループを一度にアドレス指定するために使用され、同じプロトコルを共有するコンピュータのグループを識別します。

  • クラス E: 予約アドレスであり、将来の使用のために予約されています。(240.0.0.0—255.255.255.254) このタイプの IP アドレスの最初の部分は「1111」であるため、ネットワーク番号の値は 240 ~ 255 です。

通常の IPv4 ホスト アドレスが満たされる場合、それはタイプ A、B、または C のみであり、タイプ D または E ではないことがわかります。

したがって、判断するときは、IPv4 アドレスのカテゴリ判断を増やす必要があります。

上記の判定が戻る前に、判定を追加します。

	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;
    }

完全なコードは次のとおりです。

#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));
}

この時点で、以前の非 A/B/C IPv4 アドレスを試してみましょう。

~/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

これまでのところ、基本的には比較的完璧な判断が得られていますが、抜け穴はありますか? 読者に任せて、自分で理解してください。

5 上級版

経験豊富なプログラムは、上記の判断が非常に面倒であることに気付くはずです。

このようにすべてのケースを比較して判断する必要があり、非常に手間がかかります。

もっとさわやかな高レベルの方法はありますか?

もちろん、答えはイエスです。現時点では、正規表現を理解する必要があります。

主流のプログラミング言語の多くは正規表現をサポートする標準ライブラリを持っていますが、C言語にはあるのでしょうか?

実はC言語でも正規表現が使えるのですが、ここはサスペンスにして、次の章で分解して聞いてみましょう。

プレビューへようこそ:正規表現言語 - クイック リファレンス | Microsoft Learn

6 つの完全なテスト ケース

このセクションでは、コードのテストに役立つことを期待して、さまざまなテスト ケースを追加します。

合法的测试输入
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

テスト ケースは常に充実しており、誰でも追加できます。

おすすめ

転載: blog.csdn.net/szullc/article/details/130493657