基本上求职者进行笔试没有不考字符串的。字符串也是一种相对简单的数据结构,容易被考。事实上,字符创也是一个考验程序猿编程规范和编程习惯的重要考点。ios
答案:用一个空的字符串去替换%,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 }
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 }
答案:递归的过程和这个图差很少。首先咱们先固定第一个字符,后面的剩余字符是一部分。第一步我么先把第一个字符和后面的全部字符进行交换,得出第一个字符的全部可能(第一个字符可能出现的状况列出),以后咱们在后面的字符部分当作一个字符串重复前面的方法,把第二个字符和后面的全部字符进行交换,得出其余的状况,依次递归重复上面的方法,直到最后一位字符中止。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 }
答案:因为题目出现了与字符出现次数相关。咱们能够利用一个容器来存放每一个字符出现的次数,也就是说这个容器的做用是把一个字符隐射成一个数字。因此咱们利用哈希表。算法
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 }
答案:这里咱们能够考虑一种两次翻转字符串的方法:第一次先是将字符串所有翻转,而后第二次将每一个单词翻转,这样就实现了题目的要求。所有翻转比较容易实现就是首尾字符交换就好了,给出两个指针指向首尾,进行交换。编程
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 }
答案:这个题目其实和上面那个差很少,咱们能够这样处理:咱们先分别把前面后面两部分进行翻转,获得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 }
答案:这个题目看上去十分简单,可是若是仔细考虑不少状况的也不是很简单,好比一些特殊状况:空指针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 }
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 }
答案:函数
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,因此在分配空间的时候要给源字符串和目标字符串留有足够的空间。