C/C++編程筆記:C語(yǔ)言字符串轉(zhuǎn)換知識(shí)點(diǎn)!字符轉(zhuǎn)數(shù)字,數(shù)字轉(zhuǎn)字符
在C/C++語(yǔ)言中沒(méi)有專門(mén)的字符串變量,通常用字符數(shù)組來(lái)存放字符串。字符串是以“\0”作為結(jié)束符。C/C++提供了豐富的字符串處理函數(shù),下面列出了幾個(gè)最常用的函數(shù)。

● 字符串輸出函數(shù)puts。
● 字符串輸出函數(shù)gets。
● 字符串連接函數(shù)strcat。
● 字符串復(fù)制函數(shù)strcpy。
● 測(cè)字符串長(zhǎng)度函數(shù)strlen。
字符串是面試的重點(diǎn)考查部分的相關(guān)知識(shí),通過(guò)考查字符串的相關(guān)知識(shí)可以考察程序員的編程規(guī)范以及編程習(xí)慣。并且其中包括了許多知識(shí)點(diǎn),例如內(nèi)存越界、指針與數(shù)組操作等。許多公司在面試時(shí)會(huì)要求應(yīng)聘者寫(xiě)一段復(fù)制字符串或字符串子串操作的程序。本章列舉了一些與字符串相關(guān)的面試題,有些題目要求較高的編程技巧。
數(shù)字與字符串的轉(zhuǎn)化
應(yīng)聘時(shí)經(jīng)常出現(xiàn)數(shù)字與字符串之間轉(zhuǎn)化的問(wèn)題,面試官通過(guò)這類題目來(lái)考察應(yīng)聘者能力,例如是否熟悉常用的庫(kù)函數(shù),是否了解ASCII碼以及是否了解字符串的存儲(chǔ)格式等。
數(shù)字轉(zhuǎn)化為字符串
面試?yán)}1:使用庫(kù)函數(shù)將數(shù)字轉(zhuǎn)換為字符串。
考點(diǎn):C庫(kù)函數(shù)中數(shù)字轉(zhuǎn)換為字符串的使用。
出現(xiàn)頻率:★★★
解析
C語(yǔ)言提供了幾個(gè)標(biāo)準(zhǔn)庫(kù)函數(shù),可以將任意類型(整型、長(zhǎng)整型、浮點(diǎn)型等)的數(shù)字轉(zhuǎn)換為字符串,下面列舉了各函數(shù)的方法及其說(shuō)明。
● itoa():將整型值轉(zhuǎn)換為字符串。
● ltoa():將長(zhǎng)整型值轉(zhuǎn)換為字符串。
● ultoa():將無(wú)符號(hào)長(zhǎng)整型值轉(zhuǎn)換為字符串。
● gcvt():將浮點(diǎn)型數(shù)轉(zhuǎn)換為字符串,取四舍五入。
● ecvt():將雙精度浮點(diǎn)型值轉(zhuǎn)換為字符串,轉(zhuǎn)換結(jié)果中不包含十進(jìn)制小數(shù)點(diǎn)。
● fcvt():指定位數(shù)為轉(zhuǎn)換精度,其余同ecvt()。
還可以使用sprintf系列函數(shù)把數(shù)字轉(zhuǎn)換成字符串,其比itoa()系列函數(shù)運(yùn)行速度慢。下列程序演示了如何使用itoa()函數(shù)和gcvt()函數(shù):

程序輸出結(jié)果:
?str_int: 435
?str_double: 435.10001
● 代碼第11行中的參數(shù)10表示按十進(jìn)制類型進(jìn)行轉(zhuǎn)換,轉(zhuǎn)換后的結(jié)果是“435”,如果按二進(jìn)制類型進(jìn)行轉(zhuǎn)換,則結(jié)果為“1101110011”。
● 代碼第12行中的參數(shù)8表示精確位數(shù),這里得到的結(jié)果是“435.10001”。
答案
可以使用atoi系列函數(shù)把數(shù)字轉(zhuǎn)換成字符串。
面試?yán)}2:不使用庫(kù)函數(shù)將整數(shù)轉(zhuǎn)換為字符串。
考點(diǎn):數(shù)字轉(zhuǎn)換為字符串,理解相關(guān)ASCII碼。
出現(xiàn)頻率:★★★★
解析
如果不使用atoi或sprintf等庫(kù)函數(shù),可以通過(guò)把整數(shù)的各位上的數(shù)字加“0”轉(zhuǎn)換成char類型并存到字符數(shù)組中。但是要注意,需要采用字符串逆序的方法。如以下程序所示:


程序中的int2str函數(shù)完成了int類型到字符串類型的轉(zhuǎn)換。在代碼第46行對(duì)int2str函數(shù)做了測(cè)試。程序的執(zhí)行結(jié)果如下所示:
Please input an integer: 1234
Output: 1234
如果輸入的是個(gè)負(fù)數(shù),程序執(zhí)行結(jié)果如下所示:
Please input an integer: -1234
Output: -1234
接下來(lái)對(duì)int2str函數(shù)的實(shí)現(xiàn)進(jìn)行分析。
● 代碼第9行,把參數(shù)n的絕對(duì)值賦給temp,以后在計(jì)算各個(gè)位的整數(shù)時(shí)用temp,這樣保證在負(fù)數(shù)情況下取余不會(huì)出現(xiàn)問(wèn)題。
● 代碼第11~第14行判斷str的有效性,str不為NULL。
● 代碼第15~第19行的while循環(huán)中,將n的各個(gè)位存放到局部數(shù)組buf中,存放的順序與整數(shù)順序相反。例如n為整數(shù)123456,while循環(huán)結(jié)束后buf應(yīng)為“654321”。
● 代碼第21行計(jì)算轉(zhuǎn)換后字符串的長(zhǎng)度len,如果是負(fù)數(shù),長(zhǎng)度應(yīng)該再加1。
● 代碼第22~第31行把數(shù)組buf中的非0元素逆向復(fù)制到參數(shù)str指向的內(nèi)存中,如果n是負(fù)數(shù),則str指向的第一個(gè)內(nèi)存存放負(fù)號(hào)。
字符串轉(zhuǎn)化為數(shù)字
面試?yán)}3:使用庫(kù)函數(shù)將字符串轉(zhuǎn)換為數(shù)字。
考點(diǎn):C庫(kù)函數(shù)中字符串轉(zhuǎn)換為數(shù)字的使用。
出現(xiàn)頻率:★★★★
解析
與上節(jié)數(shù)字轉(zhuǎn)換為字符串類似,C/C++語(yǔ)言提供了幾個(gè)標(biāo)準(zhǔn)庫(kù)函數(shù),可以將字符串轉(zhuǎn)換為任意類型(整型、長(zhǎng)整型、浮點(diǎn)型等)。以下列舉了各函數(shù)的方法及其說(shuō)明。
● atof():將字符串轉(zhuǎn)換為雙精度浮點(diǎn)型值。
● atoi():將字符串轉(zhuǎn)換為整型值。
● atol():將字符串轉(zhuǎn)換為長(zhǎng)整型值。
● strtod():將字符串轉(zhuǎn)換為雙精度浮點(diǎn)型值,并報(bào)告不能被轉(zhuǎn)換的所有剩余數(shù)字。
● strtol():將字符串轉(zhuǎn)換為長(zhǎng)整值,并報(bào)告不能被轉(zhuǎn)換的所有剩余數(shù)字。
● strtoul():將字符串轉(zhuǎn)換為無(wú)符號(hào)長(zhǎng)整型值,并報(bào)告不能被轉(zhuǎn)換的所有剩余數(shù)字。
以下程序演示如何使用atoi ()函數(shù)和atof ()函數(shù)。

輸出結(jié)果:
num_int: 435
num_double: 436.550000
面試?yán)}4:不使用庫(kù)函數(shù)將字符串轉(zhuǎn)換為數(shù)字。
考點(diǎn):字符串轉(zhuǎn)換為數(shù)字時(shí),對(duì)相關(guān)ASCII碼的理解。
出現(xiàn)頻率:★★★★
解析
程序代碼如下:


程序執(zhí)行結(jié)果:
輸入:1234
輸出:1234
輸入:-1234
輸出:-1234
輸入:+1234
輸出:1234
程序中的str2int函數(shù)作用是將字符串轉(zhuǎn)換成整數(shù)。這個(gè)函數(shù)的轉(zhuǎn)換過(guò)程與例題2中的int2str函數(shù)相比更加簡(jiǎn)單,它只需要做一次while循環(huán)(代碼第13行)就能把數(shù)值大小計(jì)算出來(lái),如果結(jié)果是負(fù)數(shù),就加一個(gè)負(fù)號(hào)。
C++字符串,數(shù)字相互轉(zhuǎn)換
一.將CString轉(zhuǎn)為CTime的幾種方法
CString?timestr?=?"2000年04月05日";
?int?a,b,c;
sscanf(timestr.GetBuffer(timestr.GetLength()),"%d年%d月%d日",&a,&b,&c);
?CTimetime(a,b,c,0,0,0);
--------or - ---------------------
CString?s("2001-8-29?19:06:23");
?int?nYear,nMonth,?nDate,?nHour,?nMin,?nSec;
?sscanf(s,?"%d-%d-%d?%d:%d:%d",&nYear,?&nMonth,?&nDate,&nHour,?&nMin,?&nSec);
?CTime?t(nYear,?nMonth,?nDate,?nHour,?nMin,?nSec);
---- or ------------------------
CString?timestr?=?"2000年04月05日";
?int?year,month,day;
?BYTE?tt[5];
?//get?year
?memset(tt,?0,?sizeof(tt));
?tt[0]?=timestr[0];
?tt[1]?=timestr[1];
?tt[2]?=timestr[2];
?tt[3]?=timestr[3];
?year=?atoi((char?*)tt);
?//get?month
?memset(tt,?0,?sizeof(tt));
?tt[0]?=timestr[6];
?tt[1]?=timestr[7];
?month?=atoi((char?*)tt);
?//get?day
?memset(tt,?0,?sizeof(tt));
?tt[0]?=timestr[10];
?tt[1]?=timestr[11];
?CTimetime(year,month,day,0,0,0);
從上面來(lái)看,很明顯使用sscanf()函數(shù)的優(yōu)勢(shì).
二.將CTIme轉(zhuǎn)換為CString的方法:
CTime?tmSCan =?CTime::GetCurrentTime();
CString szTime = tmScan.Format("'%Y-%m-%d %H:%M:%S'");
這樣得到的日期時(shí)間字符串就是以"2006-11-27 23:30:59"的格式.這是不是很方便呢?
//取得CTime中的日期
CString cstrDate = tmScan.Format("%Y-%m-%d");
//取得CTime中的時(shí)間
CString cstrTime = tmScan.Format("%H:%M-%S");
sprintf還有個(gè)不錯(cuò)的表妹:strftime,專門(mén)用于格式化時(shí)間字符串的,用法跟她表哥很像,也是一大堆格式控制符,只是畢竟小姑娘家心細(xì),她還要調(diào)用者指定緩沖區(qū)的最大長(zhǎng)度,可能是為了在出現(xiàn)問(wèn)題時(shí)可以推卸責(zé)任吧。這里舉個(gè)例子:
time_t t = time(0);
//產(chǎn)生"YYYY-MM-DD hh:mm:ss"格式的字符串。
char s[32];
strftime(s, sizeof(s), "%Y-%m-%d %H:%M:%S", localtime(&t));
sprintf在MFC中也能找到他的知音:CString::Format,strftime在MFC中自然也有她的同道:CTime::Format,這一對(duì)由于從面向?qū)ο竽睦锏玫搅速澲靡詫?xiě)出的代碼更覺(jué)優(yōu)雅。
三,字符串轉(zhuǎn)換為數(shù)值類型
將字符串"20.0E6"轉(zhuǎn)換為數(shù)字
1,sscanf("20.0e5","%d",&x);
2,atof("20.0E6");
許多人用atoi(), atof() 和這個(gè)“家族”中的其它函數(shù). 它們方便應(yīng)用,但是有一個(gè)重要的缺點(diǎn):
在轉(zhuǎn)換失敗和轉(zhuǎn)換字符串"0"時(shí)都返回0, 這樣使得一致性錯(cuò)誤檢查變得幾乎不可能。 為了完整性我們給出了小段代碼:
代碼:
--------------------------------------------------------------------------------
?const char* str_int = "777";
?const char* str_float = "333.3";
?int i = atoi(str_int);
?float f = atof(str_float);
--------------------------------------------------------------------------------
一個(gè)更好的辦法:
更有一點(diǎn)復(fù)雜, 更遺一致的辦法是利用sscanf()
代碼:
--------------------------------------------------------------------------------
?const char* str_int = "777";
?const char* str_float = "333.3";
?int i;
?float f;
?if(EOF == sscanf(str_int, "%d", &i)){
//錯(cuò)誤
?}
?if(EOF == sscanf(str_float, "%f", &f)){
//錯(cuò)誤
?}
--------------------------------------------------------------------------------
Since sscanf() takes a const char* parameter, you can directly use a CString with it:
因?yàn)閟scanf()用const char* 作為參數(shù), 所以你可以直接用CString作參數(shù):
代碼:
--------------------------------------------------------------------------------
?CString str_int("777");
?if(EOF == sscanf(str_int, "%d", &i)){
//error
?}
--------------------------------------------------------------------------------
小心格式描述符(如本例中的"%d")。 sscanf()沒(méi)有辦法檢查格式描述符與傳遞變量的類型匹配與否。如果不匹配你將得到不可預(yù)期的結(jié)果。 同樣注意sscanf()可以一次從字符串中提取一個(gè)或多個(gè)數(shù)值。?
C++ 方法
如下的例子展示了利用標(biāo)準(zhǔn)C++類的來(lái)完成這個(gè)任務(wù)的模板函數(shù)
代碼:
--------------------------------------------------------------------------------

四,int char * float and CStringCovernt
1。 int <->CString
1) int ->CString
int n = 1;
CString str;
str.Format("%d",n);
2) CString->int
CString str = "1";
int n = atoi(str.GetBuffer(0));
2. char* 與CString
1)char*->CString
char sz[128];
CString str;
str.Format("%s",sz);
2) CString -> char*
CString str;
//int nLength = str.GetLength();
char* sz = str.GetBuffer(0);
3. float<->CString
1)float->CString
float f = 0.0;
CString str;
str.Format("%f",f);
2) CString->float
CString str = "0.0";
float f = atof(str.GetBuffer(0));

學(xué)習(xí)C/C++編程知識(shí),提升C/C++編程能力,歡迎關(guān)注UP一起來(lái)成長(zhǎng)~
UP上傳了一些學(xué)習(xí)C/C++編程知識(shí)的視頻教程,有興趣的小伙伴可以去看一下,希望對(duì)大家有幫助!