1. 程式人生 > >IP地址字串轉無符號整型uint

IP地址字串轉無符號整型uint


考慮到轉換的過程是處理數字和點,可以使用自動機的思想;
自動機的思想就是整一個狀態-轉移表,根據輸入自動判斷,
說白了就是正則表示式,在同一個狀態下,不同的輸入會轉到不同的狀態上去。
對於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");
	}
}