考虑到转换的过程是处理数字和点,可以使用自动机的思想;
自动机的思想就是整一个状态-转移表,根据输入自动判断,
说白了就是正则表达式,在同一个状态下,不同的输入会转到不同的状态上去。
对于ip,就只有两个状态,要么是正在输入数字,要么是正在输入点,至于点和数字的个数以及数字大小等情况可以另外优化。
如果当前状态是正在输入数字,那么接下来的输入应该是数字,如果是数字则转入正在输入点的状态,否则返回错误。
如果当前的状态是正在输入点,则接下来的输入应该是点,如果是点则转入正在输入数字状态;如果是数字,
则说明数字还未接受结束,继续接受,然后维持该状态;如果是结束符则结算,否则返回错误。
#include <iostream>
#include <string>
using namespace std;
#define IPLEN 16 // 设输入ip地址长度不超过16
enum STATECODE // 状态
{
ERROR = -1,
SUCCESS,
READING_DOT,
READING_NUM
};
/* ip to unint
* 一般返回一个int作为errorCode,真正的返回值放在参数里
* para: ip,ip字符串; result,计算结果
* return: ERROR & SUCCESS
*/
int ipToUnint(char * ip, unsigned int & result)
{
if(NULL == ip)
{
return ERROR;
}
unsigned int digit = 0; // ip地址的每个整数
int dotNum = 0; // num of dot
int digitNum = 0; // num of digit
char input = 0; // 当前输入字符
int state = READING_NUM; // state
for(int i = 0; ; ++i)
{
input = ip[i];
if(state == READING_NUM) // 状态 reading num
{
if(input >= '0' && input <= '9')
{
state = READING_DOT;
digit = input - '0';
}else
{
return ERROR;
}
}else // 状态 reading dot
{
if(input >= '0' && input <= '9')
{
digit = digit * 10 + (input-'0');
if(digit > 255 || digit < 0)
{
return ERROR;
}
}else if(input == '.')
{
if(dotNum == 3)
{
return ERROR;
}
++dotNum;
result = (result<<8) + digit;
digit = 0;
state = READING_NUM;
}else if(input == '\0')
{
if(dotNum != 3)
{
return ERROR;
}
result = (result<<8) + digit;
return SUCCESS;
}else
{
return ERROR;
}
}
}
}
void main()
{
char ipStr[IPLEN] = {0};
string input = "";
cin>>input;
sscanf(input.c_str(), "%15s", ipStr);
unsigned int result = 0;
if(ipToUnint(ipStr, result) != ERROR)
{
printf("result: %d\n", result);
}else
{
printf("ERROR!\n");
}
}