C和C++中的字符串和數字轉換

在做題時經常會遇到字符串和數字轉換,當然方法也各不相同,在此我想把各種方法的特點和利弊總結一下。

測試程序示例:
以下測試結果有偶然性,僅供參考。

#include<iostream>
#include<time.h>
#include<stdlib.h>
using namespace std;

int main()
{
    char *a = "12345.6";
    double num = 11;
    int t_start, t_end;
    t_start = clock();
    for (int i = 0; i < 100000; ++i)
    {
        num = atoi(a);
    }
    t_end = clock();
    cout <<"time: "<<t_end - t_start << endl;
    cout << "result: "<<num;
    getchar();
    return 0;
}

一、C語言中的標準庫函數
參考資料
http://blog.csdn.net/sunquana/article/details/14645079
http://www.jb51.net/article/58452.htm
頭文件:# include <stdlib.h>
[tip: 命名規則是:ascii to int/float/long int 等]
接收的格式是字符數組名或指針。
1. atoi() 將字符串轉換爲整型值

char *a = "12345.6";
num = atoi(a);

轉換100000次耗時約20毫秒,轉換的數字越大,耗時越長。
可以順利轉換整數,輸入小數時會忽略小數點後的部分不會四捨五入,輸入123a456等內容是,只會輸出合法的前幾位,比如輸出123,如果從第一個字符開始就不合法,會輸出0,當超出int範圍時得到2147483647,也就是int能表示的最大的數字。

  1. atol() 將字符串轉換爲長整型值
char *a = "12345.6";
num = atol(a);

轉換100000次耗時約23毫秒,轉換的數字越大,耗時越長。
其他性質和atoi類似。

  1. atof() 將字符串轉換爲雙精度浮點型值
char *a = "12345.6";
num = atol(a);

轉換100000次耗時約90毫秒,轉換的數字越大,耗時越長。
當輸入的數字超過一個小數點時,忽略第二個小數點前的部分,當輸入的內容包含非法字符時,輸出該字符前的部分,當輸入的數字從第一個字符開始不合法時,輸出0,認可“.8”這種表示方式,會輸出0.8,但是如果輸入“-0.a”會輸出-0,但是判斷它是否小於0時,編譯器的反饋是否,判斷它是否等於0時, 編譯器的反饋是是

  1. strtod() 將字符串轉換爲雙精度浮點型值,並報告不能被轉換的所有剩餘數字
char *a = "12345.6";
char *leftover;
num = strtod(a,&leftover);

轉換100000次耗時約95毫秒,轉換的數字越大,耗時越長。
總得來說和atof()差不多,不同之處在於,會把不能轉換的部分保存在strtod()的第二個參數,leftover所指向的字符串中。

  1. strtol() 將字符串轉換爲長整值,並報告不能被轉換的所有剩餘數字
char *a = "12345.6";
char *leftover;
num = strtol(a,&leftover,10);

轉換100000次耗時約20毫秒,轉換的數字越大,耗時越長。
strtol()要接收三個參數,最後一個是進制。總得來說和atol()差不多,會把不能轉換的部分保存在strtol()的第二個參數,leftover所指向的字符串中。
可以讀取十六進制,十六進制中的“a”和“A”都是認的,0x前綴加不加都一樣,函數認爲這是一個合法的前綴。

  1. strtoul() 將字符串轉換爲無符號長整型值,並報告不能被轉換的所有剩餘數字
char *a = "12345.6";
char *leftover;
num = strtoul(a,&leftover,10);

轉換100000次耗時約20毫秒,轉換的數字越大,耗時越長。
總得來說和strtoul()差不多。
當輸入的是負數時,並不會表示該數非法,而是當它是一個無符號長整型處理。

  1. _itoa_s() 將整型轉換爲指定進制的字符串存放在字符串數組中(字符爲char類型)
double num = 12345.6;
char a[100];
_itoa_s(num,a,100,10);

是_itoa()的安全版本,第二個參數必須是指定好範圍的char*或是char數組名。第三個參數是存放轉換結果的字符串長度,第四個參數是基數。
轉換100000次耗時約9毫秒,轉換的數字越大,耗時越長。
那些所謂非法字符的情況是不太可能出現的,因爲在賦值的時候就會出問題,送入函數的一般是合法的整型數字。

  1. _itow_s() 將整型轉換爲指定進制的寬字符串存放在寬字符串數組中(字符爲wchar_t類型,根據環境不同佔兩個字節或四個字節)
double num = 12345.6;
wchar_t a[100];
_itoa_s(num,a,100,10);

是_itow()的安全版本,第二個參數必須是指定好範圍的wchar_t*或是wchar_t數組名。第三個參數是存放轉換結果的寬字符串長度,第四個參數是基數。
轉換100000次耗時約9毫秒,轉換的數字越大,耗時越長。
和_itoa_s()差不多,但是由於是wchar_t 類型,cout的時候看起來會不太一樣,設斷點看數組中的內容是沒有問題的。

二、sscanf()和sprintf()
參考資料
http://www.cnblogs.com/Anker/p/3351168.html
頭文件:#include <stdio.h>

  1. sscanf() 字符串轉數字
    功能包括:
    (1)根據格式從字符串中提取數據。如從字符串中取出整數、浮點數和字符串等。
    (2)取指定長度的字符串
    (3)取到指定字符爲止的字符串
    (4)取僅包含指定字符集的字符串
    (5)取到指定字符集爲止的字符串
int num;
char a[100]=“12345.6”;
sscanf_s(a,"%d",&num);

轉換100000次耗時約75毫秒,轉換的數字越大,耗時越長。
第一個參數可以是數組名也可以是設定好範圍的char*指針。
其實掌握了scanf也就掌握了sscanf_s,兩者有很多共同之處,這裏不再贅述。

  1. sprintf()_s 數字轉字符串
    功能包括:
    (1)將數字變量轉換爲字符串。
    (2)得到整型變量的16進制和8進制字符串。
    (3)連接多個字符串。
int num = 12345.6;
char a[100];
sprintf_s(a,"0x%X",num);

第一個參數只接受數組名,不接受指針。
轉換100000次耗時約40毫秒,轉換的數字越大,耗時越長。
連接字符串的方法爲:`sprintf_s(str,”%s %s”,s1,s2);

三、輸入輸出流
參考資料
http://blog.csdn.net/lichengiggs/article/details/722867
http://blog.csdn.net/yang3wei/article/details/25693695
頭文件:#include<sstream>
這裏其實只要把流當成cin和cout一樣就好了。

string a="12345.6";
stringstream ss;
//ss << "222222222222222222";
ss << a;
ss >> num;

轉換100000次耗時約47毫秒,轉換的數字越大,耗時越長。
但是在這裏如果添加上註釋掉的那一行,得到的就不會是我們期望的結果,這是由於流中的內容沒有清空造成的。清空流的方法是:用clear方法清空流的狀態,再用.str(“”)方法清空流的內容

ss.clear();
ss.str("");

實際使用時,如果要重複使用一個流,顯然每次使用都要清空流,那麼將清空語句放在循環體內比較更加公平。這時花費時間暴增,轉換100000次耗時約850毫秒。因此,真正投入實際使用時,雖然輸入輸出流是一種很方便的互轉方式,但是在時間上代價比較大。

總結:
上述一、二、三中,花費時間從短到長依次爲一,二,三。
在不需要清空流的情形下,二和三的耗時差不多。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章