1. 程式人生 > >C++數值與字串相互轉換的那些事(一)字串轉數值(轉載請註明)

C++數值與字串相互轉換的那些事(一)字串轉數值(轉載請註明)

以前一門心思搞演算法,這個東西覺得自己寫個函式就能實現的事,但是到了公司後才發現同事寫的程式碼裡面,呼叫各種庫函式、window API、流來實現。什麼都不懂的我表示鴨梨很大,今天翻了翻資料瞭解了下各種方法的使用方法、區別以及適用範圍,寫成了這篇又長又臭又沒條理的東西。

注:以下字串均特指空終止的字串(字串以'\0‘(一個位元組的0)結束,寬字串(本文中指UTF-8不涉及UTF-16及其他)以‘\0’(兩個位元組的0))

1.字串轉換為數值

1.1使用現成c庫函式將10進位制字串轉換為數值(c庫函式不提供其他進位制轉換

所屬標頭檔案<cstdlib>

atoi()、_wtoi()、atol()、_wtol()、atof()、_wtol()、_atoi64()、_wtoi64(),_w打頭為相應寬字元版本不逐一介紹。

atoi()函式原型如下,將字串轉換為int型別

int   atoi(   const   char   *string);

_wtoi()函式原型如下,將寬字串轉換為int型別

int _wtoi(const wchar_t *);

atol()函式原型如下,將字串轉化為long

 long  atol(const char *);
atof()函式原型如下,將字串轉化為doulbe
double atof(const char *);

_atoi64()函式原型如下,將字串轉化為__int64(long long int)
__int64 _atoi64(const char *);
例如:
#include <windows.h>
#include <iostream>
#include <cstdlib>
using namespace std;

int main()
{
	
	char szBuff[100]="1000.2121";
	int iTest = 0;
	double dTest = 0.0;
	long lTest = 0;
	__int64 i64Test = 0;
	iTest = atoi(szBuff);
	dTest = atof(szBuff);
	lTest = atol(szBuff);
	i64Test = _atoi64(szBuff);
        printf("iTest = %d\n",iTest);
	printf("lTest = %ld\n",lTest);
	printf("dTest = %lf\n",dTest);
	printf("i64Test = %I64d\n",i64Test);
	return 0;
}
輸出結果:
iTest = 1000
lTest = 1000
dTest = 1000.212100
i64Test = 1000
1.2使用現成Windows API將字串轉換為數值(Windows API 不提供浮點型別的轉換,不支援64位整數

1.2.1使用現成Windows API將10進位制字串轉換為數值

所屬標頭檔案<shlwapi.h>

注:使用時注意引入"shlwapi.lib"

StrToInt()(Widows一個相容的函式,當定義了UNICODE時表示StrToIntW,否則表示StrToIntA,以下不一一列舉)、StrToLong

 StrToInt()函式原型如下,將字串轉換為int(以下均一ANSI字串為例,UNICODE不再列舉)

int    StrToIntA(LPCSTR lpSrc);
StrToLong()函式原型如下,將字串轉換為long(其實Windows 32位機器int和long沒區別)
#define StrToLong               StrToInt
1.2.1使用現成Windows API將10或者16進位制字串轉換為數值(不支援浮點型別,不支援64位整數

所屬標頭檔案<shlwapi.h>

注:使用時注意引入"shlwapi.lib"

StrToIntEx。(注:無StrToLongEx

StrToIntEx函式原型如下,將任意進位制字串轉換為int型別,轉換成功返回TRUE,否則為FALSE

BOOL    StrToIntExA(LPCSTR pszString, DWORD dwFlags, int FAR * piRet);
第一個引數表示待轉換的字串,第二個字串用來表示待轉換的字串是16進位制還是10進位制,當dwFlags為STIF_DEFAULT表示10進位制,當dwFlags為

STIF_SUPPORT_HEX時表示10進位制。第三個引數代表一個指向int的指標(指向轉換後的值)

例如:

#include <windows.h>
#include <iostream>
#include <cstdlib>
#include <shlwapi.h>
using namespace std;

#pragma comment(lib,"shlwapi.lib")

int main()
{
	
	int   value;
	char szHex[100] = "0xFF";
        StrToIntExA(szHex,STIF_SUPPORT_HEX,&value);
	printf("%d\n",value);
	return 0;
}

輸出結果為:
255

1.3使用流將字串轉換為數值(64位流操作不支援,支援10進位制,16進位制,8進位制)以ANSI為例

所屬標頭檔案<sstream>

預定義以下巨集

#define MY_OCT 1  //8進位制
#define MY_DEC 2  //10進位制
#define MY_HEX 3 //16進位制

通過自定義函式來說明:myStrToIntExA()、myStrToLongExA()、myStrToDoubleA()。(double型別僅支援10進位制

myStrToIntExA()函式如下,將字串轉int

int myStrToIntExA(char *s,const int &iFlags = MY_DEC)
{   
	int num;
	stringstream ss(s);
	switch (iFlags)
	{
	case MY_OCT:
		ss>>std::oct>>num;//8進位制
		break;
	case MY_DEC:
		ss>>std::dec>>num;//10
		break;
	case MY_HEX:
		ss>>std::hex>>num;
		break;
	default:
		break;
	}
	return num;
}

myStrToLongExA()函式如下,將字串轉long
long myStrToLongExA(char *s,const int &iFlags = MY_DEC)
{
	long num;
	stringstream ss(s);
	switch (iFlags)
	{
	case MY_OCT:
		ss>>std::oct>>num;//8進位制
		break;
	case MY_DEC:
		ss>>std::dec>>num;//10
		break;
	case MY_HEX:
		ss>>std::hex>>num;
		break;
	default:
		break;
	}
	return num;
}
myStrToDoubleA()函式如下,將字串轉double
double myStrToDoulbeA(char *s)
{   
	double num;
	stringstream ss(s);
	ss>>num;
	return num;
}

例如:
#include <sstream>
#include <iostream>
using namespace std;
#define MY_OCT 1  //8進位制
#define MY_DEC 2  //10進位制
#define MY_HEX 3 //16進位制

int myStrToIntExA(char *s,const int &iFlags = MY_DEC)
{   
	int num;
	stringstream ss(s);
	switch (iFlags)
	{
	case MY_OCT:
		ss>>std::oct>>num;//8進位制
		break;
	case MY_DEC:
		ss>>std::dec>>num;//10
		break;
	case MY_HEX:
		ss>>std::hex>>num;
		break;
	default:
		break;
	}
	return num;
}
double myStrToDoulbeA(char *s)
{   
	double num;
	stringstream ss(s);
	ss>>num;
	return num;
}
long myStrToLongExA(char *s,const int &iFlags = MY_DEC)
{
	long num;
	stringstream ss(s);
	switch (iFlags)
	{
	case MY_OCT:
		ss>>std::oct>>num;//8進位制
		break;
	case MY_DEC:
		ss>>std::dec>>num;//10
		break;
	case MY_HEX:
		ss>>std::hex>>num;
		break;
	default:
		break;
	}
	return num;
}

int main()
{
         char str[] = "11";  
	 int  iTest = myStrToIntExA(str,MY_HEX);
	 long lTest = myStrToLongExA(str,MY_HEX);
	 double dTest = myStrToDoulbeA(str);
         printf("%d\n",iTest);
	 printf("%ld\n",lTest);
	 printf("%lf\n",dTest);
	 return 0;
}

輸出結果:
17
17
11.000000

3種方法的優劣如下表所示

64位整數 浮點數 2進位制 寬字元 8進位制 10進位制 16進位制 特點
庫函式 支援 支援 不支援 支援 不支援 支援 不支援 效率高
windows API 不支援 不支援 不支援 支援 不支援 支援 支援 效率較高
不支援 僅支援10進位制 不支援 支援 支援 支援 支援 效率較低

總體來說

庫函式唯一支援64位整數,效率高,

windows API 相容性好,效率較高

流 支援進位制多且支援10進位制浮點轉換,但是效率不高。

如果想支援非10進位制的64位整數和浮點數,只能乖乖自己實現了,建議用第一種方式進行進位制轉換就OK了