RM新时代网站-首页

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

【經(jīng)典面試題】請(qǐng)使用C語(yǔ)言編程實(shí)現(xiàn)對(duì)IPV4地址的合法性判斷

嵌入式物聯(lián)網(wǎng)開發(fā) ? 來(lái)源: 嵌入式物聯(lián)網(wǎng)開發(fā) ? 作者: 嵌入式物聯(lián)網(wǎng)開發(fā) ? 2023-05-16 15:23 ? 次閱讀

**C語(yǔ)言編程實(shí)現(xiàn)對(duì)IPV4地址的合法性判斷**

> 有了解過(guò)我的朋友,可能有點(diǎn)印象,我在N年前的博客中,就寫了這個(gè)主題,當(dāng)時(shí)確實(shí)是工作中遇到了這個(gè)問(wèn)題。本想著等工作搞完之后,就把這個(gè)問(wèn)題的解決代碼補(bǔ)上,結(jié)果一鴿,就是好幾年,真是慚愧。現(xiàn)在把這部分代碼公開,歡迎大家來(lái)下載測(cè)試。

@[toc]
# 1 寫在前面

有了解過(guò)我的朋友,可能有點(diǎn)印象,我在N年前的博客中,就寫了這個(gè)主題,當(dāng)時(shí)確實(shí)是工作中遇到了這個(gè)問(wèn)題。本想著等工作搞完之后,就把這個(gè)問(wèn)題的解決代碼補(bǔ)上,結(jié)果一鴿,就是好幾年,真是慚愧?,F(xiàn)在把這部分代碼公開,歡迎大家來(lái)下載測(cè)試。

如果你發(fā)現(xiàn)代碼有問(wèn)題,歡迎與我私信聯(lián)系。

# 2 需求分析

其實(shí),本專題的需求很簡(jiǎn)單,就是輸入一段字符串,判斷它是不是合法的IPv4地址。僅僅從功能上看,似乎很簡(jiǎn)單,但是真正要做到很完美,也是需要下點(diǎn)功夫的。不信,你看看下文的拆解。

![IPV4 的圖像結(jié)果](https://img-blog.csdnimg.cn/img_convert/994e3109304e34a6bbd59db8247d37c6.jpeg)

# 3 簡(jiǎn)單版本

我們先上一個(gè)簡(jiǎn)單版本,直接看代碼:

```c
#include
#include
#include
#include

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 %sn", ip);
printf("ret %dn", check_is_valid_ipv4(ip));
}
```

編譯運(yùn)行一下,輸入一個(gè)常見的ipv4地址是沒有問(wèn)題,比如 "192.168.0.1";同時(shí),非法的字符輸入也是會(huì)報(bào)錯(cuò)的。

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

但是,如果我加一個(gè)限制:如何判斷一個(gè)IPV4地址是一個(gè)合法的 **主機(jī)地址** 呢?

比如這個(gè):“238.171.84.41”,它的判斷還是合法的哦,實(shí)際上這不是合法的 **主機(jī)地址** 。

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

另外一個(gè),上面的代碼還檢測(cè)不到,諸如此類的輸入:“0192.168.1.1”

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

所以,我們需要優(yōu)化一下。

# 4 進(jìn)階一下

正如上面的分析,我們需要對(duì)代碼進(jìn)行優(yōu)化:

首先得判斷按照 "." 分割后的數(shù)字段,不能以 "0" 字符開頭。

```c
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
```

根據(jù)IPv4地址的分類:

- A類:(1.0.0.1-126.255.255.254)(默認(rèn)子網(wǎng)掩碼:255.0.0.0或0xFF000000)第一個(gè)字節(jié)為網(wǎng)絡(luò)號(hào),后三個(gè)字節(jié)為主機(jī)號(hào),表示為網(wǎng)絡(luò)--主機(jī)--主機(jī)--主機(jī)。該類IP地址的最前面為“0”,所以地址的網(wǎng)絡(luò)號(hào)取值于1~126之間。共有16777214個(gè)主機(jī)地址,一般用于大型網(wǎng)絡(luò)。

- B類:(128.1.0.1-191.254.255.254)(默認(rèn)子網(wǎng)掩碼:255.255.0.0或0xFFFF0000)前兩個(gè)字節(jié)為網(wǎng)絡(luò)號(hào),后兩個(gè)字節(jié)為主機(jī)號(hào)。該類IP地址的最前面為“10”,所以地址的網(wǎng)絡(luò)號(hào)取值于128~191之間。共有65534個(gè)主機(jī)地址,一般用于中等規(guī)模網(wǎng)絡(luò)。

- C類:(192.0.1.1-223.255.254.254)(子網(wǎng)掩碼:255.255.255.0或0xFFFFFF00)前三個(gè)字節(jié)為網(wǎng)絡(luò)號(hào),最后一個(gè)字節(jié)為主機(jī)號(hào)。該類IP地址的最前面為“110”,所以地址的網(wǎng)絡(luò)號(hào)取值于192~223之間。共有254個(gè)主機(jī)地址,一般用于小型網(wǎng)絡(luò)。

- D類:是多播地址。(224.0.0.1-239.255.255.254) 該類IP地址的前面4位為“1110”,所以網(wǎng)絡(luò)號(hào)取值于224~239之間;后面28位為組播地址ID。這是一個(gè)專門保留的地址。它并不指向特定的網(wǎng)絡(luò),目前這一類地址被用在多點(diǎn)廣播(Multicasting)中。多點(diǎn)廣播地址用來(lái)一次尋址一組計(jì)算機(jī),它標(biāo)識(shí)共享同一協(xié)議的一組計(jì)算機(jī)。

- E類:是保留地址,為將來(lái)使用保留。(240.0.0.0---255.255.255.254) 該類IP地址的最前面為“1111”,所以網(wǎng)絡(luò)號(hào)取值于240~255之間。

可知,如果要符合一個(gè)正常的IPv4主機(jī)地址,只能是A、B、C類,而不能是D、E類。

所以在判斷時(shí),我們應(yīng)該增加IPv4地址的類別判斷。

在上面的判斷返回前,增加一個(gè)判斷:

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

完整的代碼如下:

```c
#include
#include
#include
#include

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 %sn", ip);
printf("ret %dn", check_is_valid_ipv4(ip));
}
```

這個(gè)時(shí)候,我們?cè)僭囈幌轮暗姆茿/B/C類的IPv4地址:

```c
~/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 高階版本

有經(jīng)驗(yàn)的程序一定會(huì)發(fā)現(xiàn),上面的各個(gè)判斷真的號(hào)麻煩?。?/p>

每個(gè)case都需要這樣去比較判斷,那得多費(fèi)勁?。?/p>

有沒有更加清爽一點(diǎn)的高階方法???

答案當(dāng)然是有的,這個(gè)時(shí)候你就需要了解一下:**正則表達(dá)式** 了。

很多主流的編程語(yǔ)言都有標(biāo)準(zhǔn)庫(kù)來(lái)支持正則表達(dá)式,那么C語(yǔ)言里面有沒有呢?

其實(shí)C語(yǔ)言里面也是可以用正則表達(dá)式的,這個(gè)先留個(gè)懸念,且聽下回分解。

歡迎打擊提前預(yù)習(xí)下:[正則表達(dá)式語(yǔ)言 - 快速參考 | Microsoft Learn](https://learn.microsoft.com/zh-cn/dotnet/standard/base-types/regular-expression-language-quick-reference)

# 6 完整測(cè)試用例

本小節(jié)給大家補(bǔ)充一下各種測(cè)試用例,希望對(duì)大家測(cè)試代碼有幫助:

```c
合法的測(cè)試輸入
192.168.0.1
10.0.0.1
172.16.0.1
255.255.255.255

非法的測(cè)試輸入
256.0.0.1
192.168.0.0.1
192.168.0
192.168.0.1.2

非法的測(cè)試輸入
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
```

測(cè)試用例是不斷豐富的,歡迎大家來(lái)補(bǔ)充。

審核編輯黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • C語(yǔ)言
    +關(guān)注

    關(guān)注

    180

    文章

    7604

    瀏覽量

    136683
  • IPv4
    +關(guān)注

    關(guān)注

    0

    文章

    142

    瀏覽量

    19890
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    C語(yǔ)言進(jìn)階】面試題請(qǐng)使用宏定義實(shí)現(xiàn)字節(jié)對(duì)齊

    C語(yǔ)言進(jìn)階】面試題請(qǐng)使用宏定義實(shí)現(xiàn)字節(jié)對(duì)齊
    的頭像 發(fā)表于 07-11 09:21 ?2789次閱讀
    【<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>進(jìn)階】<b class='flag-5'>面試題</b>:<b class='flag-5'>請(qǐng)使用</b>宏定義<b class='flag-5'>實(shí)現(xiàn)</b>字節(jié)對(duì)齊

    《Visual C# 2008程序設(shè)計(jì)經(jīng)典案例設(shè)計(jì)與實(shí)現(xiàn)》---判斷主機(jī)IP合法性算法

    《Visual C# 2008程序設(shè)計(jì)經(jīng)典案例設(shè)計(jì)與實(shí)現(xiàn)》---判斷主機(jī)IP合法性算法.zip[hide][/hide]
    發(fā)表于 05-14 10:16

    java經(jīng)典面試題深度解析

    回答面試題Int 與Integer的區(qū)別第三節(jié) 以數(shù)據(jù)結(jié)構(gòu)挖掘集合面試考點(diǎn)第四節(jié) 經(jīng)典面試題重載與重寫第五節(jié) 如何回答面試官提問(wèn)Java的接
    發(fā)表于 06-20 15:16

    C語(yǔ)言 經(jīng)典面試題

    C語(yǔ)言經(jīng)典面試題目.doc
    發(fā)表于 08-05 22:03

    c語(yǔ)言面試題,c++面試題下載

    c語(yǔ)言面試題,c++面試題1. static有什么用途?(請(qǐng)至少說(shuō)明兩種) 1) 限制變量的作用域 2) 設(shè)置變量的存儲(chǔ)域 2.&
    發(fā)表于 10-22 11:19 ?5次下載

    c語(yǔ)言面試題

    c語(yǔ)言面試題集(單片機(jī))C language problem(20151125084232)
    發(fā)表于 12-18 14:05 ?9次下載

    c語(yǔ)言面試題

    c語(yǔ)言面試題
    發(fā)表于 11-05 16:48 ?0次下載

    C語(yǔ)言經(jīng)典面試題

    面試題
    發(fā)表于 12-20 22:41 ?0次下載

    C語(yǔ)言經(jīng)典面試題

    C語(yǔ)言 經(jīng)典面試題
    發(fā)表于 01-05 11:27 ?0次下載

    經(jīng)典硬件面試題精選及解答

    經(jīng)典硬件面試題精選及解答
    發(fā)表于 11-29 18:02 ?0次下載

    剩余地址分配完畢,全球IPv4地址徹底用完了

    長(zhǎng)期以來(lái),全球IPv4地址耗盡令人擔(dān)憂,今天這一時(shí)刻終于來(lái)臨——所有43億個(gè)IPv4地址已分配完畢,這意味著沒有更多的IPv4
    的頭像 發(fā)表于 11-26 10:39 ?5754次閱讀

    IPv4地址耗盡后,IPv6部署計(jì)劃如何了

    11月25日,歐洲的IPv4 地址正式宣布徹底分配完了。而早在2016年,亞太地區(qū)的IPv4地址池也已經(jīng)完全耗盡,沒有新的IP 地址可供分配
    的頭像 發(fā)表于 12-03 14:54 ?2905次閱讀

    C語(yǔ)言經(jīng)典面試題】static關(guān)鍵字的作用有哪些?

    經(jīng)典面試題,有必要了解下!
    的頭像 發(fā)表于 10-02 12:00 ?2669次閱讀
    【<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b><b class='flag-5'>經(jīng)典</b><b class='flag-5'>面試題</b>】static關(guān)鍵字的作用有哪些?

    C語(yǔ)言進(jìn)階】面試題請(qǐng)使用代碼判斷主機(jī)存儲(chǔ)屬于大端模式還是小端模式?

    經(jīng)典面試題,有必要了解下!
    的頭像 發(fā)表于 10-02 11:56 ?2354次閱讀
    【<b class='flag-5'>C</b><b class='flag-5'>語(yǔ)言</b>進(jìn)階】<b class='flag-5'>面試題</b>:<b class='flag-5'>請(qǐng)使用</b>代碼<b class='flag-5'>判斷</b>主機(jī)存儲(chǔ)屬于大端模式還是小端模式?

    IP地址IPV4IPV6的區(qū)別

    IPV4互聯(lián)協(xié)議版本4,有版本V4之前就有IPV1 IPV2IPV3,同樣有IPV5
    發(fā)表于 10-26 10:41 ?2795次閱讀
    IP<b class='flag-5'>地址</b>:<b class='flag-5'>IPV4</b>和<b class='flag-5'>IPV</b>6的區(qū)別
    RM新时代网站-首页