C++面試筆記--字符串

    基本上求職者進行筆試沒有不考字符串的。字符串也是一種相對簡單的數據結構,容易被考。事實上,字符創也是一個考驗程序猿編程規範和編程習慣的重要考點。ios

  

一、替換空格:實現一個函數,把字符串中的每一個空格替換成「%20」。例如輸入「we are happy。」則輸出「we%20are%20happy。」

    答案:用一個空的字符串去替換%,2,0三個字符,那麼原字符就會變長從而覆蓋掉後面的字符,我麼能夠考慮建立一個新的字符串並在新的字符串上面作替換,那樣就可以分配足夠的內存了。在這裏咱們能夠考慮從後往前去替換字符串。這裏建立兩個指針c++

    

 1 #include<iostream>
 2 #include <string>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<stdlib.h>
 6 using namespace std;
 7 /*
 8         算法原理:準備兩個指針p1,p2;p1指向原始字符串的末尾,p2指向替換以後的字符串的末尾。接下來咱們向前移動指針p1,
 9                 逐個把它指向的字符複製到p2指向的位置,知道碰到第一個空格爲止,
10         算法:先遍歷一次字符串,記錄空格的數目,在計算新的字符數組的長度
11                 在從後往前進行替換
12 */
13 char *copystr(char *s)
14 {
15     int len=strlen(s);//字符串的長度
16     int blank=0;//表示空格的數目
17     if(len==0)
18     {
19         return NULL;
20     }
21     if(s==NULL)
22     {
23         return NULL;
24     }
25     
26     for(int i=0; i<len; i++) //判斷字符串,肯定空格的數目,從而肯定新的字符串所需的個數
27     {
28         if(s[i]==' ')
29             blank++;
30     }
31     if(blank==0)
32         return s;
33     int new_len=blank*2+len;//計算新的字符數組的長度(原本不應加一,可是最後的輸出要求加一)
34     int l=new_len+1;//這裏'\0'也算一個長度
35     char *str1;
36     for(int i=len; i>=0; i--)//算法:有空格就賦值,沒有空格直接複製,從後往前複製
37     {
38         if(s[i]!=' ')//從後往前複製
39         {
40             str1[l-1]=s[i];
41             l--;
42         }
43         else//轉換空格
44         {
45             str1[l-1]='0';
46             str1[l-2]='2';
47             str1[l-3]='%';
48             l-=3;
49         }
50     }
51     return str1;
52 }
53 int main()
54 {
55 static char str[10000000];
56     gets(str);
57     char *dest = copystr(str);
58     if(dest != NULL)
59         puts(dest);
60     dest = NULL;
61     return 0;
62 
63 }
View Code

 

 1 #include<iostream>
 2 #include <string>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<stdlib.h>
 6 using namespace std;
 7 /*
 8         算法原理:準備兩個指針p1,p2;p1指向原始字符串的末尾,p2指向替換以後的字符串的末尾。接下來咱們向前移動指針p1,
 9                 逐個把它指向的字符複製到p2指向的位置,知道碰到第一個空格爲止,
10         算法:先遍歷一次字符串,記錄空格的數目,在計算新的字符數組的長度
11                 在從後往前進行替換
12 */
13 char *copystr(char *s)
14 {
15     int len=strlen(s);//字符串的長度
16     int blank=0;//表示空格的數目
17     if(len==0)
18     {
19         return NULL;
20     }
21     if(s==NULL)
22     {
23         return NULL;
24     }
25     for(int i=0; i<len; i++) //判斷字符串,肯定空格的數目,從而肯定新的字符串所需的個數
26     {
27         if(s[i]==' ')
28             blank++;
29     }
30     if(blank==0)
31         return s;
32     int new_len=blank*2+len;//計算新的字符數組的長度(原本不應加一,可是最後的輸出要求加一)
33     int l=new_len+1;
34 //    char *str1 = (char *)malloc(new_len*sizeof(char)+1);
35     char *str1;
36     for(int i=len; i>=0; i--)//算法:有空格就賦值,沒有空格直接轉換
37     {
38         if(s[i]!=' ')
39         {
40             str1[l-1]=s[i];
41             l--;
42         }
43         else
44         {
45             str1[l-1]='0';
46             str1[l-2]='2';
47             str1[l-3]='%';
48             l-=3;
49         }
50     }
51     return str1;
52 }
53 int main()
54 {
55 static char str[10000000];
56     gets(str);
57     char *dest = copystr(str);
58     if(dest != NULL)
59         puts(dest);
60     dest = NULL;
61     return 0;
62 
63 }

二、字符串的排列:輸入一個字符串,打印出該字符串中字符的全部排列。例如:輸入字符串abc,則打印出由字符a,b,c所能排列出來的全部字符串abc,acb,bac,bca,cab,cba

 答案:遞歸的過程和這個圖差很少。首先咱們先固定第一個字符,後面的剩餘字符是一部分。第一步我麼先把第一個字符和後面的全部字符進行交換,得出第一個字符的全部可能(第一個字符可能出現的狀況列出),以後咱們在後面的字符部分當作一個字符串重複前面的方法,把第二個字符和後面的全部字符進行交換,得出其餘的狀況,依次遞歸重複上面的方法,直到最後一位字符中止。git

 
 1 #include<iostream>
 2 #include<cstring>
 3 #include<stdlib.h>
 4 using namespace std;
 5 /*
 6         解題思路:
 7                 1.就是將字符串從第一個字符開始,依次和後面的字符進行交換,知道交換到末尾爲止
 8                          ①      ②
 9                 2.好比:abcd--acbd,a,a,a,--
10                         bacd--bcad--
11                         cbad--cabd--
12                         dbca--dcba--
13                 3.可是這個算法是不能有重複的字符的操做
14 */
15 /*
16         交換函數:將先後兩個字符進行交換
17 */
18 int swap_str(char *str1,char *str2){
19     char temp=*str1;
20     *str1=*str2;
21     *str2=temp;
22 }
23 /*這個函數是輸出排列的函數*/
24 void permutation(char *str1,char *begin){
25     if(*begin=='\0')//當遞歸到末尾的時候,輸出該排列
26         cout<<str1<<endl;
27     else{
28         for(char *ch=begin;*ch!='\0';*ch++){//從子字符串進行遞歸
29             swap_str(ch,begin);
30             permutation(str1,begin+1);
31             swap_str(ch,begin);
32         }
33     }
34 }
35 void permutation(char *str){
36     if(str==NULL)
37         return ;
38     permutation(str,str);
39 }
40 
41 int main(){
42     char str[]="abc";
43     permutation(str,str);
44     return 0;
45 }
View Code

 

三、第一個只出現一次的字符:在字符串中找出第一個只出現一次的字符。如輸入「abaccdeff」則輸出b

 答案:因爲題目出現了與字符出現次數相關。咱們能夠利用一個容器來存放每一個字符出現的次數,也就是說這個容器的做用是把一個字符隱射成一個數字。因此咱們利用哈希表。算法

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 #include<cstring>
 5 using namespace std;
 6 char Find_Only_one_char(char *string){
 7     /*①:字符char是一個長度爲8的數據類型,一個字節,在32位的操做系統中有256中可能組合。
 8       咱們建立一個長度爲256的數組,每一個字母根據其ASSIC碼做爲數組的下標對應數組的一個數字
 9       而數組中存儲的是每一個字符穿線的次數。
10       ②:複雜度:第一次遍歷數組更新一個字符出現次數的時間爲O(1),N個就是O(N),第二次遍歷讀取一個字符
11          的時間是O(1),N個就是O(N),因此總的是O(N)*/
12     if(string==NULL)
13         return '\0';
14     const int hashsize=256;//表示256個字符的Assic
15     unsigned int hashtable[hashsize];//哈希容器
16     for(unsigned int i=0;i<hashsize;i++)
17         hashtable[hashsize]=0;//初始化哈希數組
18 
19     //開始進行第一次的遍歷,若是出現一個字符,則將改字符對應的hash數加1,建立一個字符指針進行遍歷
20     char *string1=string;
21     while(*(string1)!='\0'){
22             //這裏string1++:string1最後地址會加1,可是*(string1++)仍是當前的地址不會加1,因此a++是後加,++a是先加
23         hashtable[*(string1++)]++;//地址加加,對應的字符的hash數也是加加
24     }
25     //從新讓指針指向字符串首部再進行一次遍歷
26     string1=string;
27 
28     while(*string1!='\0'){
29         if(hashtable[*string]==1)
30             return *string;
31         string++;//地址加加,繼續遍歷下一個字符
32     }
33     return '\0';
34 }
35 int main(){
36     char string[10000];
37     while(scanf("%s",string)!=EOF){
38         cout<<Find_Only_one_char(string)<<endl;
39     }
40 //    delete []string;
41 }
View Code

 

 

四、翻轉單詞順序VS左旋轉字符串:題目一:輸入一個英語句子,翻轉句子中單詞的順序,可是單詞的字符的順序不變。變電符號和普通字符同樣處理。

 答案:這裏咱們能夠考慮一種兩次翻轉字符串的方法:第一次先是將字符串所有翻轉,而後第二次將每一個單詞翻轉,這樣就實現了題目的要求。所有翻轉比較容易實現就是首尾字符交換就好了,給出兩個指針指向首尾,進行交換。編程

 1 #include<iostream>
 2 #include<stdlib.h>
 3 #include<cstring>
 4 #include<cstdio>
 5 using namespace std;
 6 /*這裏咱們能夠經過單詞的空格來肯定某個單詞的起始位置和終止位置。而後在調用change函數就好了,這個方法至關於分治法。
 7   先是總體,而後分紅每一個單詞部分翻轉。*/
 8 void Change_Oneword_Order(char *begin,char *behind){
 9     if(begin>behind)
10         return ;
11     while(begin<behind){//遍歷一個單詞,先後順序調換
12         char temp=*begin;
13         *begin=*behind;
14         *behind=temp;
15         begin++,behind--;//遍歷到單詞中間位置
16     }
17 
18 }
19 char *Change_Onestr_Order(char *str){
20     if(str==NULL)
21         return '\0';
22 
23     char *behind=str;
24     char *begin=str;
25     while(*behind!='\0')
26         behind++;
27     behind--;//第二指針向前移動一位
28 
29     Change_Oneword_Order(begin,behind);
30 
31     begin=str;//第二次進行單詞的翻轉
32     behind=str;
33 
34     while(*begin!='\0'){//臨界條件:第一指針走到字符串的末尾結束
35         if(*begin==' '){
36                 //找到空格,跳過
37             begin++;
38             behind++;
39         }
40         else if(*behind==' '|| *behind=='\0'){
41             Change_Oneword_Order(begin,--behind);//從空格前面一個字符開始翻轉
42             begin=++behind;//翻轉完成回到同一個起跑線
43         }
44         else
45             behind++;
46     }
47     return str;
48 }
49 void print(char *str){
50     cout<<str;
51 }
52 int main(){
53     char s[1000];
54     gets(s);
55     char *ss=Change_Onestr_Order(s);
56     print(ss);
57 }
View Code

    題目二:字符串的左旋轉操做是吧字符串前面的若干個字符轉移到字符串的尾部。定義一個函數實現字符串左旋轉操做功能。好比輸入字符串「abcdef」和2,返回cdefab.

 答案:這個題目其實和上面那個差很少,咱們能夠這樣處理:咱們先分別把前面後面兩部分進行翻轉,獲得bafedc,而後咱們在翻轉整個字符串獲得cdefab,這樣就好了。其實咱們也是能夠先總體翻轉而後在局部翻轉,可是在局部反轉的時候很差找到翻轉位置,實現不如前面方法好。數組

 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 using namespace std;
 5 void Change_Oneword_Order(char *begin,char *behind){
 6     if(begin>behind)
 7         return ;
 8     while(begin<behind){//遍歷一個單詞,先後順序調換
 9         char temp=*begin;
10         *begin=*behind;
11         *behind=temp;
12         begin++,behind--;//遍歷到單詞中間位置
13     }
14 
15 }
16 char *Left_Revolve_Str(char *str,int number){
17     if(str!=NULL){
18         int length=static_cast<int>(strlen(str));
19 
20         if(length>0 &&number>0 &&number<length){
21             //第一部分:0->n
22             char *firststart=str;
23             char *firstend=str+number-1;
24             //第二部分:n->length
25             char *secondstart=str+number;
26             char *secondend=str+length-1;
27             //翻轉前半部分
28             Change_Oneword_Order(firststart,firstend);
29             //翻轉後半部分
30             Change_Oneword_Order(secondstart,secondend);
31             //翻轉總體
32             Change_Oneword_Order(firststart,secondend);
33         }
34     }
35     return str;
36 }
37 void print(char *str){
38     cout<<str;
39 }
40 int main(){
41     int number;
42     cin>>number;
43     char s[1000];
44     cin>>s;
45     char *ss=Left_Revolve_Str(s,number);
46     print(ss);
47 }
View Code

五、怎樣將整數轉換成字符串數,而且不用函數 itoa ?

    答案:這個題目看上去十分簡單,可是若是仔細考慮不少狀況的也不是很簡單,好比一些特殊狀況:空指針NULL,空字符串,正負號,溢出等方面的測試數據結構

  詳細版本:app

 1 #include<iostream>
 2 using namespace std;
 3 long long strToCore(const char *,bool );
 4 enum status{valid=0,invalid=1};
 5 int g_status=valid;
 6 
 7 int strToInt(const char *str){
 8     g_status=invalid;
 9     long long num=0;
10 
11     if(str!=NULL && *str!='\0'){//不爲空也沒溢出
12         bool minus=false;
13         if(*str=='+')
14             str++;
15         else if(*str=='-'){
16             str++;
17             minus=true;
18         }
19         num=strToCore(str,minus);
20     }
21     return num;
22 }
23 long long strToCore(const char *digit,bool minus){
24     long long num=0;
25     while(*digit!='\0'){
26         if(*digit>='0' &&*digit<='9'){
27             int flag=minus?-1:1;
28             num=num*10+flag*(*digit-'0');
29             //這裏沒有考慮溢出的狀況
30             digit++;
31         }
32         else{
33             num=0;
34             break;
35         }
36     }
37     if(*digit=='\0')
38         g_status=valid;
39     return num;
40 }
41 int main(){
42     int num=0;
43     num=strToInt("2345");
44     cout<<num;
45 }
View Code

  itao版本:ide

 1 #include <iostream>
 2 
 3 #include <stdlib.h>
 4 
 5 using namespace std;
 6 
 7  
 8 
 9 //使用itoa函數
10 
11 int main ()
12 
13 {
14 
15     int num=12345;
16 
17     char str[7];
18 
19  
20 
21     itoa(num,str,10);
22 
23     cout<<"integer:"<<num<<endl<<"string:"<<str<<endl;
24 
25     return 0;
26 
27 }
View Code

 

六、已知函數原型是 char *strcpy(char *strDest,const char *strSrc);,其中strDest是目的字符串,strSrc是源字符串。

    (1)不調用C++/C的字符串庫函數,請編寫strcpy函數。

    (2)strcpy函數把strSrc的內容複製到strDest,爲何還要char *類型返回值?

    答案:函數

  

char *strcpy(char *strDest,const char *strSrc)
{
    assert((strDest!=NULL)&&(strSrc!=NULL));
    char *address=strDest;
    while((*strDest++=*strSrc++)!='\0')
    NULL;
    return address;
}

(2)爲了實現鏈式表達式,返回具體值。

例如:

int length=strlen(strcpy(strDest,"hello world"));

 

七、下面程序輸出是什麼?

  

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<cstring>
 4 using namespace std;
 5 int main(){
 6     char s[]="1234567890";
 7     char d[]="123";
 8     strcpy(d,s);
 9     cout<<d<<endl<<s<<endl;
10 }

 

    答案:輸出結果是1234567890,567890.緣由:當初分配的內存地址是連續內存的關係(從後往前存儲),原來是:123\01234567890\0,strcpy變成了1234567890\0567890\0,因此在分配空間的時候要給源字符串和目標字符串留有足夠的空間。

相關文章
相關標籤/搜索