在C/C++語言中沒有專門的字符串變量,通常用字符數組來存放字符串。字符串是以“\0”作為結束符。C/C++提供了豐富的字符串處理函數,下面列出了幾個最常用的函數。
● 字符串輸出函數puts。
● 字符串輸出函數gets。
● 字符串連接函數strcat。
● 字符串復制函數strcpy。
● 測字符串長度函數strlen。
字符串是面試的重點考查部分的相關知識,通過考查字符串的相關知識可以考察程序員的編程規范以及編程習慣。並且其中包括了許多知識點,例如內存越界、指針與數組操作等。許多公司在面試時會要求應聘者寫一段復制字符串或字符串子串操作的程序。本章列舉了一些與字符串相關的面試題,有些題目要求較高的編程技巧。
6.1 數字與字符串的轉化
應聘時經常出現數字與字符串之間轉化的問題,面試官通過這類題目來考察應聘者能力,例如是否熟悉常用的庫函數,是否了解ASCII碼以及是否了解字符串的存儲格式等。
6.1.1 數字轉化為字符串
面試例題1:使用庫函數將數字轉換為字符串。
考點:C庫函數中數字轉換為字符串的使用。
出現頻率:★★★
解析
C語言提供了幾個標准庫函數,可以將任意類型(整型、長整型、浮點型等)的數字轉換為字符串,下面列舉了各函數的方法及其說明。
● itoa():將整型值轉換為字符串。
● ltoa():將長整型值轉換為字符串。
● ultoa():將無符號長整型值轉換為字符串。
● gcvt():將浮點型數轉換為字符串,取四舍五入。
● ecvt():將雙精度浮點型值轉換為字符串,轉換結果中不包含十進制小數點。
● fcvt():指定位數為轉換精度,其余同ecvt()。
還可以使用sprintf系列函數把數字轉換成字符串,其比itoa()系列函數運行速度慢。下列程序演示了如何使用itoa()函數和gcvt()函數:
1 # include <stdio.h>
2 # include <stdlib.h>
3
4 int main ()
5 {
6 int num_int = 435;
7 double num_double = 435.10f;
8 char str_int[30];
9 char str_double[30];
10
11 itoa(num_int, str_int, 10); //把整數num_int轉成字符串str_int
12 gcvt(num_double, 8, str_double); //把浮點數num_double轉成字符串str_double
13
14 printf("str_int: %s\n", str_int);
15 printf("str_double: %s\n", str_double);
16
17 return 0;
18 }
程序輸出結果:
1 str_int: 435
2 str_double: 435.10001
● 代碼第11行中的參數10表示按十進制類型進行轉換,轉換后的結果是“435”,如果按二進制類型進行轉換,則結果為“1101110011”。
● 代碼第12行中的參數8表示精確位數,這里得到的結果是“435.10001”。
答案
可以使用atoi系列函數把數字轉換成字符串。
面試例題2:不使用庫函數將整數轉換為字符串。
考點:數字轉換為字符串,理解相關ASCII碼。
出現頻率:★★★★
解析
如果不使用atoi或sprintf等庫函數,可以通過把整數的各位上的數字加“0”轉換成char類型並存到字符數組中。但是要注意,需要采用字符串逆序的方法。如以下程序所示:
1 #include <iostream>
2 using namespace std;
3
4 void int2str(int n, char *str)
5 {
6 char buf[10] = "";
7 int i = 0;
8 int len = 0;
9 int temp = n < 0 ? -n: n; // temp為n的絕對值
10
11 if (str == NULL)
12 {
13 return;
14 }
15 while(temp)
16 {
17 buf[i++] = (temp % 10) + '0'; //把temp的每一位上的數存入buf
18 temp = temp / 10;
19 }
20
21 len = n < 0 ? ++i: i; //如果n是負數,則多需要一位來存儲負號
22 str[i] = 0; //末尾是結束符0
23 while(1)
24 {
25 i--;
26 if (buf[len-i-1] ==0)
27 {
28 break;
29 }
30 str[i] = buf[len-i-1]; //把buf數組里的字符拷到字符串
31 }
32 if (i == 0 )
33 {
34 str[i] = '-'; //如果是負數,添加一個負號
35 }
36 }
37
38 int main()
39 {
40 int nNum;
41 char p[10];
42
43 cout << "Please input an integer:";
44 cin >> nNum;
45 cout << "output: " ;
46 int2str(nNum, p); //整型轉換成字符串
47 cout<< p << endl;
48
49 return 0;
50 }
程序中的int2str函數完成了int類型到字符串類型的轉換。在代碼第46行對int2str函數做了測試。程序的執行結果如下所示:
Please input an integer: 1234
Output: 1234
如果輸入的是個負數,程序執行結果如下所示:
Please input an integer: -1234
Output: -1234
接下來對int2str函數的實現進行分析。
● 代碼第9行,把參數n的絕對值賦給temp,以后在計算各個位的整數時用temp,這樣保證在負數情況下取余不會出現問題。
● 代碼第11~第14行判斷str的有效性,str不為NULL。
● 代碼第15~第19行的while循環中,將n的各個位存放到局部數組buf中,存放的順序與整數順序相反。例如n為整數123 456,while循環結束后buf應為“654 321”。
● 代碼第21行計算轉換后字符串的長度len,如果是負數,長度應該再加1。
● 代碼第22~第31行把數組buf中的非0元素逆向復制到參數str指向的內存中,如果n是負數,則str指向的第一個內存存放負號。
6.1.2 字符串轉化為數字
面試例題3:使用庫函數將字符串轉換為數字。
考點:C庫函數中字符串轉換為數字的使用。
出現頻率:★★★★
解析
與上節數字轉換為字符串類似,C/C++語言提供了幾個標准庫函數,可以將字符串轉換為任意類型(整型、長整型、浮點型等)。以下列舉了各函數的方法及其說明。
● atof():將字符串轉換為雙精度浮點型值。
● atoi():將字符串轉換為整型值。
● atol():將字符串轉換為長整型值。
● strtod():將字符串轉換為雙精度浮點型值,並報告不能被轉換的所有剩余數字。
● strtol():將字符串轉換為長整值,並報告不能被轉換的所有剩余數字。
● strtoul():將字符串轉換為無符號長整型值,並報告不能被轉換的所有剩余數字。
以下程序演示如何使用atoi ()函數和atof ()函數。
1 # include <stdio.h>
2 # include <stdlib.h>
3
4 int main ()
5 {
6 int num_int;
7 double num_double;
8 char str_int[30] = "435"; //將要被轉換為整型的字符串
9 char str_double[30] = "436.55"; //將要被轉換為浮點型的字符串
10
11 num_int = atoi(str_int); //轉換為整型值
12 num_double = atof(str_double); //轉換為浮點型值
13
14 printf("num_int: %d\n", num_int);
15 printf("num_double: %lf\n", num_double);
16
17 return 0;
18 }
輸出結果:
num_int: 435
num_double: 436.550000
面試例題4:不使用庫函數將字符串轉換為數字。
考點:字符串轉換為數字時,對相關ASCII碼的理解。
出現頻率:★★★★
解析
程序代碼如下:
1 #include <iostream>
2 using namespace std;
3
4 int str2int(const char *str)
5 {
6 int temp = 0;
7 const char *ptr = str; //ptr保存str字符串開頭
8
9 if (*str == '-' || *str == '+') //如果第一個字符是正負號,
10 { //則移到下一個字符
11 str++;
12 }
13 while(*str != 0)
14 {
15 if ((*str < '0') || (*str > '9')) //如果當前字符不是數字
16 { //則退出循環
17 break;
18 }
19 temp = temp * 10 + (*str - '0'); //如果當前字符是數字則計算數值
20 str++; //移到下一個字符
21 }
22 if (*ptr == '-') //如果字符串是以“-”開頭,則轉換成其相反數
23 {
24 temp = -temp;
25 }
26
27 return temp;
28 }
29
30 int main()
31 {
32 int n = 0;
33 char p[10] = "";
34
35 cin.getline(p, 20); //從終端獲取一個字符串
36 n = str2int(p); //把字符串轉換成整型數
37
38 cout << n << endl;
39
40 return 0;
41 }
程序執行結果:
輸入:1234
輸出:1234
輸入:-1234
輸出:-1234
輸入:+1234
輸出:1234
程序中的str2int函數作用是將字符串轉換成整數。這個函數的轉換過程與例題2中的int2str函數相比更加簡單,它只需要做一次while循環(代碼第13行)就能把數值大小計算出來,如果結果是負數,就加一個負號。
C++字符串,數字相互轉換
一.將CString轉為CTime的幾種方法
CString timestr = "2000年04月05日";
int a,b,c ;
sscanf(timestr.GetBuffer(timestr.GetLength()),"%d年%d月%d日",&a,&b,&c);
CTime time(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];
CTime time(year,month,day,0,0,0);
從上面來看,很明顯使用sscanf()函數的優勢.
二.將CTIme轉換為CString的方法:
CTime tmSCan = CTime::GetCurrentTime();
CString szTime = tmScan.Format("'%Y-%m-%d %H:%M:%S'");
這樣得到的日期時間字符串就是以"2006-11-27 23:30:59"的格式.這是不是很方便呢?
//取得CTime中的日期
CString cstrDate = tmScan.Format("%Y-%m-%d");
//取得CTime中的時間
CString cstrTime = tmScan.Format("%H:%M-%S");
sprintf還有個不錯的表妹:strftime,專門用於格式化時間字符串的,用法跟她表哥很像,也是一大堆格式控制符,只是畢竟小姑娘家心細,她還要調用者指定緩沖區的最大長度,可能是為了在出現問題時可以推卸責任吧。這里舉個例子:
更多更好的sprintf()函數說明參考:《spirntf,你知道多少?》
http://blog.csdn.net/steedhorse/archive/2005/03/25/330206.aspx
time_t t = time(0);
//產生"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,這一對由於從面向對象哪里得到了贊助,用以寫出的代碼更覺優雅。
三,字符串轉換為數值類型
將字符串"20.0E6"轉換為數字
1,sscanf("20.0e5","%d",&x);
2,atof("20.0E6");
許多人用atoi(), atof() 和這個“家族”中的其它函數. 它們方便應用,但是有一個重要的缺點:
在轉換失敗和轉換字符串"0"時都返回0, 這樣使得一致性錯誤檢查變得幾乎不可能。 為了完整性我們給出了小段代碼:
代碼:
--------------------------------------------------------------------------------
const char* str_int = "777";
const char* str_float = "333.3";
int i = atoi(str_int);
float f = atof(str_float);
--------------------------------------------------------------------------------
一個更好的辦法:
更有一點復雜, 更遺一致的辦法是利用sscanf()
代碼:
--------------------------------------------------------------------------------
const char* str_int = "777";
const char* str_float = "333.3";
int i;
float f;
if(EOF == sscanf(str_int, "%d", &i)){
//錯誤
}
if(EOF == sscanf(str_float, "%f", &f)){
//錯誤
}
--------------------------------------------------------------------------------
Since sscanf() takes a const char* parameter, you can directly use a CString with it:
因為sscanf()用const char* 作為參數, 所以你可以直接用CString作參數:
代碼:
--------------------------------------------------------------------------------
CString str_int("777");
if(EOF == sscanf(str_int, "%d", &i)){
//error
}
--------------------------------------------------------------------------------
小心格式描述符(如本例中的"%d")。 sscanf()沒有辦法檢查格式描述符與傳遞變量的類型匹配與否。如果不匹配你將得到不可預期的結果。 同樣注意sscanf()可以一次從字符串中提取一個或多個數值。 詳細信息請查閱MSDN。
C++ 方法
如下的例子展示了利用標准C++類的來完成這個任務的模板函數
代碼:
--------------------------------------------------------------------------------
#include <string>
#include <sstream>
#include <iostream>
template <class T>
bool from_string(T &t,
const std::string &s,
std::ios_base & (*f)(std::ios_base&))
{
std::istringstream iss(s);
return !(iss>>f>>t).fail();
}
int main()
{
int i;
float f;
// from_string()的第三個參數應為如下中的一個
// one of std::hex, std::dec 或 std::oct
if(from_string<int>(i, std::string("ff"), std::hex)){
std::cout<<i<<std::endl;
}
else{
std::cout<<"from_string failed"<<std::endl;
}
if(from_string<float>(f,
std::string("123.456"),
std::dec))
{
std::cout<<f<<std::endl;
}
else{
std::cout<<"from_string failed"<<std::endl;
}
return 0;
}
四, int char * float and CString Covernt
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));