【摘要】
字符串String - 要求字符串类型、字符数组类型,字符指针类型三大类知识点。
1.要求熟记字符串与数字的转换函数;循环移位函数;拷贝字符串函数strcpy的实现;最频繁字符串查找函数;最长复现字符串查找函数;strstr函数的实现;其中,字符指针特点在于存在移位操作和常量与变量两个属性。字符数组和字符指针可以采用C字符函数,而字符串对象则需要熟悉字符串方法。本章考察点主要有:字符类型转换,寻找字符串中高频子串,最长复现子串,字符串循环移位和字符串类方法与C方法的实现。
【正文】
字符串与数字的相互转换
string str = "123456789";cout<
【勘误】
这里是之前理解错误造成的片面曲解,字符串变量是不能等价于字符指针变量的。
现给出两者比较如下:
char *w = "12345678";
// w[3] = '9'; // 运行报错
string w = "12345678";
w[3] = '9';
char ch[ ] = {'1','2','3','4','5','6'};
char *c = ch;
c[3] = '9';
cout<<*c+2<
常用库函数atoi,itoa,strcpy,strcmp的实现 http://blog.csdn.net/jianzhibeihang/article/details/5710722;
#include <assert.h>
void assert( int expression ); // 其作用是如果它的条件返回错误,则终止程序执行
详见 assert()函数用法总结 http://www.cnblogs.com/ggzss/archive/2011/08/18/2145017.html
链式表达式就是相关表达更加方便,就像链子一样简化代码。如: int length = strlen( strcpy( strDest, “hello world”));省去了多行代码标识。
相关知识详见 关于链式表达式 http://www.cnblogs.com/hnrainll/archive/2011/04/29/2032868.html
字符串的循环右移
memcpy函数
memcpy函数详见 memcpy函数 http://blog.csdn.net/fcrane/article/details/4390991
memcpy与strcpy的比较
memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度;例:char a[100],b[50]; memcpy(b, a, sizeof(b));注意如用sizeof(a),会造成b的内存地址溢出。
strcpy就只能拷贝字符串了,它遇到'/0'就结束拷贝;例:char a[100],b[50];strcpy(a,b);如用strcpy(b,a),要注意a中的字符串长度(第一个‘/0’之前)是否超过50位,如超过,则会造成b的内存地址溢出。也可能不报错,这要看编译器。不过,报不报错这样做都是不安全的。这个时候数组要比“指针+分配动态内存”简洁。最后,在字符数据之后一定要记得加上'\0',千万记得!!!不管是字符数组还是字符指针,都最好添上,而且,字符数组最好定义大于字符数目。最后,在强调一遍,字符指针在结束处不要忘记'\0' ,这是必须的!!!
【注】面试宝典在strcpy函数上,认为指针拷贝到数组不需要考虑指针的'\0',数组拷贝到数组要保证源数组较目标数组至少小一位。换言之,面试宝典人为目标对象为数组时,必须考虑'\0'。
无符号字符 unsigned char ch;char 型数据的强制整型为-128~127,unsigned char 的强制整型转换为 0~255。
cerr:错误输出流,无缓冲,不可以重定向。输出的数据不经过缓冲区,直接放到指定的目标中,既然不经过缓冲区那么其它程序就无法把要输出的内容送到其他目标中,所以说它不能被重定向。
cout:标准输出流,有缓冲,可重定向。把要输出的数据先放到缓冲区中,然后再从缓冲区到你指定的设备中。当向cout流插入一个endl,不论缓冲区是否满了,都立即输出流中所有数据,然后插入一个换行符.
cerr不被缓冲,也就说错误消息可以直接发送到显示器,而无需等到缓冲区或者新的换行符时,才被显示。而cout是一个有缓冲的输出。关于这一点,很多的资料上都有提到,但是cerr也可以通过 rdbuf 方法重定向到文件中。
C++标准流重定向及cout和cerr的区别 http://blog.csdn.net/FromHJ/article/details/8760763
string str.substr (int val_1,int val_2)的两个参量分别表示起始值和子串长度;
1)将字符串的同后缀字符串子串集合,可输出查看;如:“12345”,同后缀集合为{“12345”;“2345”;“345”;“45”;“5”}。2)固定第 i 个子串,以它为基准往后的第 j 个子串,判断它们是否有相同的前缀子串,子串长度为(j - i)个字符。基准串 str[i].substr(0, j - i )。
a)如果没有相同子串则继续滑动 j 直到找到,如果滑动到最后一个 j 子串还没有发现,那么,就让 i 滑动到下一个;b)如果找到相同子串,则让 j 子串为基准,再往后滑动(j - i)个子串,判断与基准串的相似性。直到不同或者到子串集合末尾为止;【注】这里有个逻辑,就是连续的相同的子串。如果相同连续,那么,第 i 个子串的(j - i)字符之后,恰好就遇到第 j 个子串首字符。
3)记录每次的重复次数和子串,本次重复次数与之前最大的重复次数比较,最终输出最大重复次数。
1)求一个字符串中连续出现次数最多的子串(程序面试宝典)http://blog.csdn.net/sleeping_dog/article/details/9427075 (亮点在数据结构 pair < *,* > val ( fir,sec) );2)编程珠玑(四)求一个字符串中连续出现的次数最多的子串http://blog.csdn.net/ysu108/article/details/7795479 (亮点在动态分配内存) ;3)最新的微软面试题,题目:求一个字符串中连续出现次数最多的子串http://blog.csdn.net/phphot/article/details/2337739(亮点在接口的思想)。
pair是一种模板类型,其中包含两个数据值,两个数据的类型可以不同,基本的定义如下:
pair
a;
表示a中有两个类型元素,第一个元素是int型的,第二个元素是string类型的,如果创建pair的时候没有对其进行初始化,则调用默认构造函数对其初始化。
pair
a("James", "Joy");
也可以像上面一样在定义的时候直接对其初始化。由于pair类型的使用比较繁琐,因为如果要定义多个形同的pair类型的时候,可以时候typedef简化声明
pair
a;
表示a中有两个类型元素,第一个元素是int型的,第二个元素是string类型的,如果创建pair的时候没有对其进行初始化,则调用默认构造函数对其初始化。
pair
a("James", "Joy");
也可以像上面一样在定义的时候直接对其初始化。由于pair类型的使用比较繁琐,因为如果要定义多个形同的pair类型的时候,可以时候typedef简化声明
typedef pair
author;
author pro("May", "Lily");
author joye("James", "Joyce");
对于pair类,由于它只有两个元素,分别名为first和second,因此直接使用普通的点操作符即可访问其成员
pair
a("Lily", "Poly"); string name;
name = pair.second;
可以使用make_pair对已存在的两个数据构造一个新的pair类型:
int a = 8;
string m = "James";pair
new_one; new_one = make_pair(a, m);
pair两个成员变量的的名字就叫 first 和 second 。
pair变量可以通过pairval.first = ***;pairval.second = ***;和 pairval = make_pair(firval,secval);两种方式赋值,不同的是make_pair的第一个变量不可以是常量,只能是变量名。
见到 vector 等变量,首先想到的不应该是 vecval[i] 这一种赋值方式,而是vecval的成员函数,诸如push,push_back,pop之列。
pair相关详细详见,C++ 10.1和10.2 关联容器-----pair 类型
http://blog.csdn.net/hlsdbd1990/article/details/46438003
字符串查找函数:
1)逆序查找函数rfind;
2)正序查找函数find。
size_t,在C++中,设计 size_t 就是为了适应多个平台的 。size_t的引入增强了程序在不同平台上的可移植性。size_t是针对系统定制的一种数据类型,一般是整型。
strstr()函数详见:实现strstr()函数 http://blog.csdn.net/tianmohust/article/details/7246587
在不使用库函数的时候,处理数据最保险的是使用指针和字符数组,尤其是字符数组,安全系数最高,不容易出现溢出等问题。当然,数组的局限性很高,但是,安全系数也较高。
注意,这里有一个标点的判断,落实多种情况在面试宝典里面没有体现,可自行约束修正;
注意,不论是字符串、字符数组还是指针都要 '\0'。
这里一定要明白字符串是可以像字符数组一样操作的,字符串元素的操作跟字符串数组可以一个道理。string str = "******";str[3]是可读写,可删改的,不过以面向对象的思想来处理数组是更提倡的一种方式,不过数组方式也勉强可行,只是不高级罢了。但仅仅只是定义的字符串就不可以像这样操作了。string str;str[0] = '8';这样操作是错误的!!!
sprintf函数,详见日志 (待续) C程序设计语言--格式化输入/输出 sprintf fprintf sscanf snprintf ?sprintf (char* dst , "%format_a%format_b%format_c",val_a,val_b,val_c);//该函数,负责合成字符串,不负责输出!
【题】移动字符串内容,传入参数char *a和m,规则如下:将a中字符串的倒数m个字符移到字符串前面,其余依次像右移。例如:ABCDEFGHI,M=3,那么移到之后就是GHIABCDEF。注意不得修改原代码指针数据也可以字符数组形式读写,可以字符数组删改。看见异常点不要慌,比如题目中的 w[len-m] = '\0';熟悉或表达的执行顺序,从左至右,且一旦满足就不往右看;
【源码】
#include #include void fun(char *w,int m);void main(){char w[30];int m;printf("请输入一个字符串\n");gets(w);printf("请输入移动的字符数\n");scanf("%d",&m);fun(w,m);printf("移动后的结果为%s\n",w);}void fun(char *w,int m){int i = 0,len = strlen(w);if(m > len) // 此处对于输入的移动字符数超过字符串长度做了处理m = len;while(len-m > 0 || (m = 0) != 0) //(m=0)!=0的目的是给m赋值为0,并且不进入循环,还满足要求for(i = 0,w[len] = w[0],++m;i < len;i++) w[i] = w[i+1];w[len-m] = '\0'; //不要被表象迷惑,刚开始就以为是在中间加了'\0',然后蒙了~}msbd-4.0-P.240-5