/**********************************************************************/
/* filename: ipParser.c */
/* author: huaiwen he */
/* date: 2008.5.13 */
/**********************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
typedef unsigned long u_long;
typedef unsigned char u_char;
//存储IP 地址的数据结构
typedef union ip_addr{
u_long addr;
struct {u_char b1, b2, b3, b4;} addr_b;
} ip_addr;
//判断IP地址的类别
#define IS_CLASSA(i) (((long)(i) & 0x80000000) == 0)
#define IS_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000)
#define IS_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000)
#define IS_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000)
//有类别IP地址的子网掩码
const char* SUBNET_MASK[] ={ "255.0.0.0",
"255.255.0.0"
"255.255.255.0"};
/*函数声明*/
void ipToString(const u_long ipAddr, char str[]);
int stringToIp(const char ipStr[], u_long* ipAddr);
void printBinary(const u_long ipAddr);
int getIpClass(u_long ipAddr);
u_long getNetIdOfClassIp(const u_long ipAddr);
u_long getBAddrOfClassIp(const u_long ipAddr);
u_long getHostIdOfClassIp(const u_long ipAddr);
/**************************************************************************/
/*函数原型: u_long getNetId(u_long ipAddr) */
/*参数: u_long ipAddr 有类别的IP地址 */
/*返回值: u_long Ip地址所在的网络号网络号,如果返回值为0,表示
该IP地址不存在网络号 */
/**************************************************************************/
u_long getNetIdOfClassIp(const u_long ipAddr)
{
u_long ip_addr = ipAddr;
int ipClass;
ipClass = getIpClass(ip_addr);
switch(ipClass)
{
/*A类IP地址*/
case 0:
return (0xff000000 & ip_addr);
/*B类IP地址*/
case 1:
return (0xffff0000 & ip_addr);
/*C类IP地址*/
case 2:
return (0xffffff00 & ip_addr);
default:
printf("该IP地址不存在网络号/n");
return (u_long)0;
}
}
u_long getBAddrOfClassIp(const u_long ipAddr)
{
u_long ip_addr = ipAddr;
int ipClass;
ipClass = getIpClass(ip_addr);
switch(ipClass)
{
case 0:
return (0x00ffffff | ip_addr);
case 1:
return (0x0000ffff | ip_addr);
case 2:
return (0x000000ff | ip_addr);
default:
printf("该网络不存在广播地址/n");
return (u_long)0;
}
}
u_long getHostIdOfClassIp(const u_long ipAddr)
{
u_long ip_addr = ipAddr;
int ipClass = getIpClass(ip_addr);
switch(ipClass)
{
case 0:
return (0x00ffffff & ip_addr);
case 1:
return (0x0000ffff & ip_addr);
case 2:
return (0x000000ff & ip_addr);
default:
printf("该IP地址不存在主机号/n");
return (u_long)0;
}
}
/**********************************************************************/
/* 函数原型:ipToString(const u_long ipAddr, char str[]) */
/* 参数: u_long ipAddr(长整类型的IP地址),
char* str(数组,大小为16byte) */
/* 返回值:int,成功返回1,失败返回-1 */
/* 函数功能:将长整类型的IP地址转换为点分十进制的字符串表示形式*/
/**********************************************************************/
void ipToString(const u_long ipAddr, char str[])
{
ip_addr ip;
ip.addr = ipAddr;
sprintf(str, "%d.%d.%d.%d", ip.addr_b.b4, ip.addr_b.b3,
ip.addr_b.b2, ip.addr_b.b1);
}
/**********************************************************************/
/* 函数原型:printBinary(const u_long ipAddr) */
/* 参数: u_long ipAddr(长整类型的IP地址) */
/* 返回值:void */
/* 函数功能:打印输出一个长整形的IP地址的二进制形式 */
/**********************************************************************/
void printBinary(const u_long ipAddr)
{
int i;
u_long ip = ipAddr;
/*逐位输出最高位*/
for(i = 1; i <= 32; ++i)
{
(ip&0x80000000) ? printf("1") : printf("0");
ip <<= 1;
(i%8) ? printf("") : printf(" "); /*逢一个字节就输出空格*/
}
printf("/n");
}
/**********************************************************************/
/* 函数原型:stringToIp(const char* ipStr, u_long* ipAddr) */
/* 参数: char* ipStr(点分十进制表示的IP地址)
u_long* ipAddr(长整型的IP地址) */
/* 返回值:int */
/* 函数功能:将字符串形式的IP地址转换为长整型的IP地址,如果字符串错误
,返回-1,否则返回1. 并将IP地址存储在ipAddr中 */
/**********************************************************************/
int stringToIp(const char ipStr[], u_long* ipAddr)
{
ip_addr ip;
int byte[4]; //保存每个字节的数值
int i = 0; // 用于遍历字符串
int byteVal = 0; // 每个字节十进制数值
int dotCount = 0; // '.'符号的个数
if(ipStr == NULL)
{
printf("Bad Argument: ipAddr is invalid./n");
return -1;
}
while(ipStr[i])
{
//如果字符不为数字或者不是'.',返回-1.
if((ipStr[i] < '0'||ipStr[i] > '9')
&& (ipStr[i] != '.'))
return -1;
//字符串长度大于16,返回-1
if(i >= 16)
return (-1);
//遇到'.'字符
else if(ipStr[i] == '.')
{
//'.'次数大于3或者后一位也是'.',返回-1
if(dotCount > 3 || ipStr[i+1] == '.')
return (-1);
// 判断'.'是否出现在首位或末位
if(i == 0 || ipStr[i+1]=='/0')
return (-1);
byte[dotCount] = byteVal; // 获取前一个字节的值
dotCount++;
byteVal = 0; //重置字节的值为0
}
else
{
// 字节数值以0开头
if(byteVal == 0 && ipStr[i] == '0')
return (-1);
//计算该字节的数值
byteVal = (byteVal*10) + (ipStr[i] - '0');
if(byteVal < 0 || byteVal > 255)
return -1;
}
i++;
}
//如何'.'小于3个,返回-1
if(dotCount < 3)
return -1;
//dotCount等于3,得到最后一个字节的整数
byte[dotCount] = byteVal;
//将得到的整数组成长整型的IP地址
ip.addr_b.b1 = byte[3];
ip.addr_b.b2 = byte[2];
ip.addr_b.b3 = byte[1];
ip.addr_b.b4 = byte[0];
*ipAddr = ip.addr;
return 1;
}
/*
判断IP地址的类别
*/
int getIpClass(const u_long ipAddr)
{
if(IS_CLASSA(ipAddr))
return 0;
if(IS_CLASSB(ipAddr))
return 1;
if(IS_CLASSC(ipAddr))
return 2;
if(IS_CLASSD(ipAddr))
return 3;
else
return 4;
}
void usage()
{
printf("/n/n用法:IP地址大小为4个字节,共32位。由<网络号,主机号>两部分"
"组成。/n在计算机内往往使用一个4字节的长整型变量来存储。/n有类别"
"的IP地址分为A、B、C、D、E五类。其中常用的有A、B、C三类。/n"
"/n本程序用于分析一个有类别的IP地址.包括判断输入IP地址的合法性、/n"
"并输出IP地址的二进制表示形式,判断IP地址的类别,/n输出IP地址所在"
"的网络号、主机号以及广播地址/n"
"作者: huaiwen he/n"
"时间: 2008年5月16日/n");
}
/***************************************************************************/
/* 函数原型:pause() */
/* 返回值:void */
/* 函数功能:暂停目前的程序,用户按回车键继续 */
/***************************************************************************/
void pause()
{
fflush(stdin); /*清空输入流*/
printf("/nPlease Press Enter to continue.../n");
int ch;
while(1)
if((ch=getchar()) == '/n') /*如果不是按回车键*/
break;
}
/* 主函数 */
int main()
{
char inputStr[80]; // 输入字符串
char ipAddrStr[4*4]; // 保存IP地址字符串形式
u_long ipAddr; //保存长整数类型的IP地址
int ipClass; // 保存IP地址的类别
usage();
pause();
while(1)
{
system("cls");
printf("/n请输入一个IP地址或者输入q(Q)退出程序:/n");
scanf("%s", inputStr);
printf("/n-------------------------------------------------------/n");
/*如果输入q或者Q,推出程序*/
if((inputStr[0]=='q')||(inputStr[0] == 'Q'))
{
pause();
exit(0); /*退出程序*/
}
/*判断IP地址的合法性*/
if(stringToIp(inputStr, &ipAddr) < 0) /*非法IP地址*/
{
printf("=====Error: Bad IP Address %s./n", inputStr);
}
else
{
printf("/n输入的IP地址 %s 在系统中以unsigned long int类型存储",
inputStr);
printf("/n该IP 地址对应的二进制为:/n/t");
printBinary(ipAddr);
/*获得IP地址的类别*/
ipClass = getIpClass(ipAddr);
printf("/t该IP地址属于%c类IP/n", ('A'+ipClass));
/*获得IP地址所属的网络*/
ipToString(getNetIdOfClassIp(ipAddr), ipAddrStr);
printf("/t该IP地址的网络号为%s/n", ipAddrStr);
/*获得IP地址的主机号*/
ipToString(getHostIdOfClassIp(ipAddr), ipAddrStr);
printf("/t该IP地址的主机号为%s/n", ipAddrStr);
/*获得该网络的广播地址*/
ipToString(getBAddrOfClassIp(ipAddr), ipAddrStr);
printf("/t该网络的广播地址为%s/n", ipAddrStr);
}
pause();
}
}
/* filename: ipParser.c */
/* author: huaiwen he */
/* date: 2008.5.13 */
/**********************************************************************/
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
typedef unsigned long u_long;
typedef unsigned char u_char;
//存储IP 地址的数据结构
typedef union ip_addr{
u_long addr;
struct {u_char b1, b2, b3, b4;} addr_b;
} ip_addr;
//判断IP地址的类别
#define IS_CLASSA(i) (((long)(i) & 0x80000000) == 0)
#define IS_CLASSB(i) (((long)(i) & 0xc0000000) == 0x80000000)
#define IS_CLASSC(i) (((long)(i) & 0xe0000000) == 0xc0000000)
#define IS_CLASSD(i) (((long)(i) & 0xf0000000) == 0xe0000000)
//有类别IP地址的子网掩码
const char* SUBNET_MASK[] ={ "255.0.0.0",
"255.255.0.0"
"255.255.255.0"};
/*函数声明*/
void ipToString(const u_long ipAddr, char str[]);
int stringToIp(const char ipStr[], u_long* ipAddr);
void printBinary(const u_long ipAddr);
int getIpClass(u_long ipAddr);
u_long getNetIdOfClassIp(const u_long ipAddr);
u_long getBAddrOfClassIp(const u_long ipAddr);
u_long getHostIdOfClassIp(const u_long ipAddr);
/**************************************************************************/
/*函数原型: u_long getNetId(u_long ipAddr) */
/*参数: u_long ipAddr 有类别的IP地址 */
/*返回值: u_long Ip地址所在的网络号网络号,如果返回值为0,表示
该IP地址不存在网络号 */
/**************************************************************************/
u_long getNetIdOfClassIp(const u_long ipAddr)
{
u_long ip_addr = ipAddr;
int ipClass;
ipClass = getIpClass(ip_addr);
switch(ipClass)
{
/*A类IP地址*/
case 0:
return (0xff000000 & ip_addr);
/*B类IP地址*/
case 1:
return (0xffff0000 & ip_addr);
/*C类IP地址*/
case 2:
return (0xffffff00 & ip_addr);
default:
printf("该IP地址不存在网络号/n");
return (u_long)0;
}
}
u_long getBAddrOfClassIp(const u_long ipAddr)
{
u_long ip_addr = ipAddr;
int ipClass;
ipClass = getIpClass(ip_addr);
switch(ipClass)
{
case 0:
return (0x00ffffff | ip_addr);
case 1:
return (0x0000ffff | ip_addr);
case 2:
return (0x000000ff | ip_addr);
default:
printf("该网络不存在广播地址/n");
return (u_long)0;
}
}
u_long getHostIdOfClassIp(const u_long ipAddr)
{
u_long ip_addr = ipAddr;
int ipClass = getIpClass(ip_addr);
switch(ipClass)
{
case 0:
return (0x00ffffff & ip_addr);
case 1:
return (0x0000ffff & ip_addr);
case 2:
return (0x000000ff & ip_addr);
default:
printf("该IP地址不存在主机号/n");
return (u_long)0;
}
}
/**********************************************************************/
/* 函数原型:ipToString(const u_long ipAddr, char str[]) */
/* 参数: u_long ipAddr(长整类型的IP地址),
char* str(数组,大小为16byte) */
/* 返回值:int,成功返回1,失败返回-1 */
/* 函数功能:将长整类型的IP地址转换为点分十进制的字符串表示形式*/
/**********************************************************************/
void ipToString(const u_long ipAddr, char str[])
{
ip_addr ip;
ip.addr = ipAddr;
sprintf(str, "%d.%d.%d.%d", ip.addr_b.b4, ip.addr_b.b3,
ip.addr_b.b2, ip.addr_b.b1);
}
/**********************************************************************/
/* 函数原型:printBinary(const u_long ipAddr) */
/* 参数: u_long ipAddr(长整类型的IP地址) */
/* 返回值:void */
/* 函数功能:打印输出一个长整形的IP地址的二进制形式 */
/**********************************************************************/
void printBinary(const u_long ipAddr)
{
int i;
u_long ip = ipAddr;
/*逐位输出最高位*/
for(i = 1; i <= 32; ++i)
{
(ip&0x80000000) ? printf("1") : printf("0");
ip <<= 1;
(i%8) ? printf("") : printf(" "); /*逢一个字节就输出空格*/
}
printf("/n");
}
/**********************************************************************/
/* 函数原型:stringToIp(const char* ipStr, u_long* ipAddr) */
/* 参数: char* ipStr(点分十进制表示的IP地址)
u_long* ipAddr(长整型的IP地址) */
/* 返回值:int */
/* 函数功能:将字符串形式的IP地址转换为长整型的IP地址,如果字符串错误
,返回-1,否则返回1. 并将IP地址存储在ipAddr中 */
/**********************************************************************/
int stringToIp(const char ipStr[], u_long* ipAddr)
{
ip_addr ip;
int byte[4]; //保存每个字节的数值
int i = 0; // 用于遍历字符串
int byteVal = 0; // 每个字节十进制数值
int dotCount = 0; // '.'符号的个数
if(ipStr == NULL)
{
printf("Bad Argument: ipAddr is invalid./n");
return -1;
}
while(ipStr[i])
{
//如果字符不为数字或者不是'.',返回-1.
if((ipStr[i] < '0'||ipStr[i] > '9')
&& (ipStr[i] != '.'))
return -1;
//字符串长度大于16,返回-1
if(i >= 16)
return (-1);
//遇到'.'字符
else if(ipStr[i] == '.')
{
//'.'次数大于3或者后一位也是'.',返回-1
if(dotCount > 3 || ipStr[i+1] == '.')
return (-1);
// 判断'.'是否出现在首位或末位
if(i == 0 || ipStr[i+1]=='/0')
return (-1);
byte[dotCount] = byteVal; // 获取前一个字节的值
dotCount++;
byteVal = 0; //重置字节的值为0
}
else
{
// 字节数值以0开头
if(byteVal == 0 && ipStr[i] == '0')
return (-1);
//计算该字节的数值
byteVal = (byteVal*10) + (ipStr[i] - '0');
if(byteVal < 0 || byteVal > 255)
return -1;
}
i++;
}
//如何'.'小于3个,返回-1
if(dotCount < 3)
return -1;
//dotCount等于3,得到最后一个字节的整数
byte[dotCount] = byteVal;
//将得到的整数组成长整型的IP地址
ip.addr_b.b1 = byte[3];
ip.addr_b.b2 = byte[2];
ip.addr_b.b3 = byte[1];
ip.addr_b.b4 = byte[0];
*ipAddr = ip.addr;
return 1;
}
/*
判断IP地址的类别
*/
int getIpClass(const u_long ipAddr)
{
if(IS_CLASSA(ipAddr))
return 0;
if(IS_CLASSB(ipAddr))
return 1;
if(IS_CLASSC(ipAddr))
return 2;
if(IS_CLASSD(ipAddr))
return 3;
else
return 4;
}
void usage()
{
printf("/n/n用法:IP地址大小为4个字节,共32位。由<网络号,主机号>两部分"
"组成。/n在计算机内往往使用一个4字节的长整型变量来存储。/n有类别"
"的IP地址分为A、B、C、D、E五类。其中常用的有A、B、C三类。/n"
"/n本程序用于分析一个有类别的IP地址.包括判断输入IP地址的合法性、/n"
"并输出IP地址的二进制表示形式,判断IP地址的类别,/n输出IP地址所在"
"的网络号、主机号以及广播地址/n"
"作者: huaiwen he/n"
"时间: 2008年5月16日/n");
}
/***************************************************************************/
/* 函数原型:pause() */
/* 返回值:void */
/* 函数功能:暂停目前的程序,用户按回车键继续 */
/***************************************************************************/
void pause()
{
fflush(stdin); /*清空输入流*/
printf("/nPlease Press Enter to continue.../n");
int ch;
while(1)
if((ch=getchar()) == '/n') /*如果不是按回车键*/
break;
}
/* 主函数 */
int main()
{
char inputStr[80]; // 输入字符串
char ipAddrStr[4*4]; // 保存IP地址字符串形式
u_long ipAddr; //保存长整数类型的IP地址
int ipClass; // 保存IP地址的类别
usage();
pause();
while(1)
{
system("cls");
printf("/n请输入一个IP地址或者输入q(Q)退出程序:/n");
scanf("%s", inputStr);
printf("/n-------------------------------------------------------/n");
/*如果输入q或者Q,推出程序*/
if((inputStr[0]=='q')||(inputStr[0] == 'Q'))
{
pause();
exit(0); /*退出程序*/
}
/*判断IP地址的合法性*/
if(stringToIp(inputStr, &ipAddr) < 0) /*非法IP地址*/
{
printf("=====Error: Bad IP Address %s./n", inputStr);
}
else
{
printf("/n输入的IP地址 %s 在系统中以unsigned long int类型存储",
inputStr);
printf("/n该IP 地址对应的二进制为:/n/t");
printBinary(ipAddr);
/*获得IP地址的类别*/
ipClass = getIpClass(ipAddr);
printf("/t该IP地址属于%c类IP/n", ('A'+ipClass));
/*获得IP地址所属的网络*/
ipToString(getNetIdOfClassIp(ipAddr), ipAddrStr);
printf("/t该IP地址的网络号为%s/n", ipAddrStr);
/*获得IP地址的主机号*/
ipToString(getHostIdOfClassIp(ipAddr), ipAddrStr);
printf("/t该IP地址的主机号为%s/n", ipAddrStr);
/*获得该网络的广播地址*/
ipToString(getBAddrOfClassIp(ipAddr), ipAddrStr);
printf("/t该网络的广播地址为%s/n", ipAddrStr);
}
pause();
}
}