C++面试笔记--字符串

    基本上求职者进行笔试没有不考字符串的。字符串也是一种相对简单的数据结构,容易被考。事实上,字符创也是一个考验程序猿编程规范和编程习惯的重要考点。

  

1、替换空格:实现一个函数,把字符串中的每个空格替换成“%20”。例如输入“we are happy。”则输出“we%20are%20happy。”

    答案:用一个空的字符串去替换%,2,0三个字符,那么原字符就会变长从而覆盖掉后面的字符,我么可以考虑创建一个新的字符串并在新的字符串上面做替换,那样就能够分配足够的内存了。在这里我们可以考虑从后往前去替换字符串。这里创建两个指针

    

 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 }

2、字符串的排列:输入一个字符串,打印出该字符串中字符的所有排列。例如:输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab,cba

 答案:递归的过程和这个图差不多。首先我们先固定第一个字符,后面的剩余字符是一部分。第一步我么先把第一个字符和后面的所有字符进行交换,得出第一个字符的所有可能(第一个字符可能出现的情况列出),之后我们在后面的字符部分当做一个字符串重复前面的方法,把第二个字符和后面的所有字符进行交换,得出其他的情况,依次递归重复上面的方法,直到最后一位字符停止。

 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 }

3、第一个只出现一次的字符:在字符串中找出第一个只出现一次的字符。如输入“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 }

4、翻转单词顺序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 }

    题目二:字符串的左旋转操作是吧字符串前面的若干个字符转移到字符串的尾部。定义一个函数实现字符串左旋转操作功能。比如输入字符串“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 }

5、怎样将整数转换成字符串数,并且不用函数 itoa ?

    答案:这个题目看上去十分简单,但是如果仔细考虑很多情况的也不是很简单,比如一些特殊情况:空指针NULL,空字符串,正负号,溢出等方面的测试

  详细版本:

 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版本:

 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 }

6、已知函数原型是 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"));

7、下面程序输出是什么?

  

 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,所以在分配空间的时候要给源字符串和目标字符串留有足够的空间。

时间: 2024-10-14 11:05:23

C++面试笔记--字符串的相关文章

Java面试笔记

1.&和&& if(str != null& !str.equals("")){ System.out.println("ok"); }//抛空指针异常 if(str != null&& !str.equals("")){ System.out.println("ok"); }//正常编译 &还可以用作位运算符,当&操作符两边的表达式不是boolean类型时,&a

《python基础教程(第二版)》学习笔记 字符串(第3章)

<python基础教程(第二版)>学习笔记 字符串(第3章)所有的基本的序列操作(索引,分片,乘法,判断成员资格,求长度,求最大最小值)对字符串也适用.字符串是不可以改变的:%左侧是格式字符串,右侧是需要格式化的值print '%s=%d' % ('x',100) ==> x=100%% 格式字符串中出现 %模板字符串:from string import Templates=Template('$x is 100');  s.substitute(x='ABC');  ==> '

#面试系列 字符串处理算法

面试系列 字符串处理算法 最大子序列和 动态规划法 思路:顺序遍历,判断sum是否大于等于0 时间复杂度:O(n) 空间复杂度:O(1) #include <iostream> #include <limits.h> using namespace std; int getMaxSum(int *arr, int size) { int maxSum = INT_MIN; //负的无穷大 int sum = 0; int curstart = 0; int start = 0; i

程序员编程技术学习笔记——字符串包含

程序员编程技术学习笔记--字符串包含 1.题目描述 给定两个分别由字母组成的字符串A和字符串B,字符串B的长度比字符串A短.请问,如何最快地判断字符串B中所有字母是否都在字符串A里?为了简单起见,我们规定输入的字符串只包含大写英文字母,请实现函数boolStringContains(string &A, string &B) 比如,如果是下面两个字符串: String 1:ABCD String 2:BAD 答案是true,即String2里的字母在String1里也都有,或者说Strin

golang学习笔记————字符串

字符串的创建 在golang中 字符串是使用双引号("")包裹住的字符序列: 字符是使用单引号('')包裹住的单一字符: 声明字符串的方式:var strvalue string 声明并创建的方式:strvalue := "This is a string!"; KeyPoint: 一旦字符串变量被初始化后,则不可单独改变该字符串序列中的某一字符:但该字符串变量可以重新被赋值: Ex:   strvalue := "abcd" fmt.Print

Java学习笔记--字符串和文件IO

1.Java中的字符串类和字符的表示 2.区分String,StringBuilder和StringBuffer 3.从命令行中给main方法传递参数 4.文件操作 1 Java中的字符串和字符 1.1 String类 字符串就是由一系列的字符组成的序列,在很多语言中,比如C语言,将其存储在一个数组中.现在运用Java的思想,就要将字符串视为一个对象,其中Java规定的String类有11个构造方法,同时还有至少40种实现的方法,通过String类的学习,可以很好地了解面向对象的类和对象的思想.

Redis学习笔记---字符串类型

补充 上篇笔记博客中有些有些关键点未提到,现在这里补充下 redis help 命令 help命令应该是我们使用任何一款软件产品经常用到的命令,有时候通过help命令能够更快的获取相关帮助,而不仅仅通过百度.同样,在Redis中的help命名写的就非常简洁易懂,虽然是只有英文版的帮助信息,但是只要有一定应用基础的人都可以看懂,如: 127.0.0.1:6379> help redis-cli 3.0.2 Type: "help @<group>" to get a l

C++面试笔记--树

树 树的题目基本都是二叉树,但是面试官还没有说是不是二叉树的时候千万不要先把答案说出来,要是面试官说是多叉树,而你做的是二叉树就直接挂了! 一. 树的三种遍历.前序.中序.后序,如果直接考遍历,就肯定是让你写非递归代码的(递归版太弱智了),具体写法,要不你记下来,要不参考“递归”部分的,怎么递归转非递归,另一个就是给个中序+前序(后序),让你还原二叉树,中序必须给,不然还原不了(解不唯一),一般递归解决: 二.  BST(Binary Search Tree).这个考法多一点,怎么判断是不是BS

PHP学习笔记——字符串的操作

字符串的操作1.去除字符串的首尾空格和特殊字符 函数trim() 用于去除开始位置以及结束位置的字符 语法 string trim(string str[, string charlist]),其中charlist是可选参数,指定删除的字符串,携带的话,删除指定的字符,如果不携带的话,删除所有的可选字符. 可选字符有 \0(空值).\t(制表符).\n(换行符).\x0B(垂直制表符).\r(回车符)." "(空格) 函数ltrim() 用于去除左边的空格或者指定字符 语法 strin