1.常见的字符串操作
如计算长度,求子串等都是考验基本功的,现在基本操作进行实现,如下
2.基本实现
mchar.h
//串的基本操作(注意:里面的所有操作要求串必须以'\0'结束)
#ifndef MCHAR_H
#define MCHAR_H
//注意:这里面的i都是位置,从1开始;而数组中对应于0,从0开始
class MChar{
public:
int strLen(const char *s); //串长度(在输入串的时候,必须以'\0'结束)
char* strCpy(char* s,const char* p); //串拷贝,p拷贝给s,原来的值被覆盖
char* strCat(char* s, const char* p);//串连接,将p连接到s后面
char* subStr(char* s, int i, int len);//求从第i个位置开始的长度为len的子串
int strCmp(const char* s, const char* p); //串比较(s==p, return=0; s>p, return>0; else <0)
int strIndex(const char* s, const char* p); //子串定位(p若属于s,返回串p在s中的位置,否则返回0)
void strInsert(char* s, int i, const char* p);//将串p插入到串s的第i个字符开始的位置上
void strDelete(char* s, int i, int len);//删除串s中从第i个字符开始的长度为len的子串
int findStr(const char* s, int ch); //查找为ch的字符
const char *toUpper(char *s); //将所有小写字符转换为大写
void itoaTest(int num, char str[]); //整数转换为字符串
int atoiTest(char s[]); //字符串转换成整数atoi函数
bool isPalindrome(char *s); //判断输入的是否是一个回文字符串
void printStr(char* s);
};
#endif
mchar.cpp
#include <iostream>
#include <cstring>
#include <assert.h>
#include "mchar.h"
using namespace std;
//串长度(在输入串的时候,必须以'\0'结束)
int MChar::strLen(const char *s){
if(!s) throw "串不能为空!\n";
int i=0;
while(*s != '\0'){
i++;
s++;
}
return i;
}
//串拷贝,p拷贝给s,原来的值被覆盖
char* MChar::strCpy(char* s,const char* p){
if(!s || !p) throw "串不能为空!\n";
char *address = s;
//改进1,简洁
//while(*p != '\0') *s++ = *p++;
while((*s++ = *p++) != '\0');
//改进2:去掉它*s = '\0';
//改进3:增加返回值,返回最新的s地址,方便链式操作
return address;
}
//串连接,将p连接到s后面
char* MChar::strCat(char* s, const char* p){
if(!s || !p) throw "串不能为空!\n";
while(*s != '\0') *s++;
while(*p != '\0') *s++ = *p++;
*s = '\0';
return s;
}
//求从第i个位置开始的长度为len的子串
char* MChar::subStr(char* s, int i, int len){
if(!s) throw "串不能为空!\n";
int l = strLen(s);
if(i<1 || i>l || i+len-2>l) throw "参数越界异常!\n";
int j=1;
char* t = s;
while(j != i && *s != '\0'){
j++;
*s++;
}
while(*s != '\0' && len > 0)
{
len--;
*t++ = *s++;
}
*t = '\0';
return t;
}
//串比较(s==p, return=0; s>p, return 1; else -1)
int MChar::strCmp(const char* s, const char* p){
if(!s || !p) throw "串不能为空!\n";
while(*s != '\0'){
if(*s++ == *p++) continue;
else if(*s++ > *p++) return 1;
else return -1;
}
if(*s == '\0' && *p == '\0') return 0;
else return -1;
}
//将串p插入到串s的第i个字符开始的位置上,假设s的长度足够长,不会溢出
void MChar::strInsert(char* s, int i, const char* p){
if(!s && !p) throw "串不能为空!\n";
int len = strLen(s);
int len2 = strLen(p);
if(i<1 || i>len+1) throw "参数越界异常!\n";
int j=0;
//不是j=len-1开始,因为要把'\0'也移动到后面
for(j=len; j>=i-1; j--){
s[len2+j] = s[j];
}
for(j=0; j<len2; j++){
s[i+j-1] = p[j];
}
}
//删除串s中从第i个字符开始的长度为len的子串
void MChar::strDelete(char* s, int i, int len){
if(!s) throw "串不能为空!\n";
int l = strLen(s);
if(i<1 || i>l || i+len-1> l) throw "参数越界异常!\n";
for(int j=i+len-1; j<=l; j++){
s[j-len] = s[j];
}
}
//查找为ch的字符
int MChar::findStr(const char* s, int ch){
if(!s) throw "串不能为空!\n";
int i=1;
while(*s != '\0'){
if(*s == (char)ch) return i;
s++;
i++;
}
return 0;
}
//子串定位(p若属于s,返回串p在s中的位置,否则返回0)
int MChar::strIndex(const char* s, const char* p){
if(!s || !p) throw "串不能为空!\n";
int i=0, j=0, r = 1;
int sl = strLen(s);
int pl = strLen(p);
if(sl < pl) throw "参数异常,串长度!\n";
while(i<sl && j<pl){
if(s[i] == p[j]){
i++; j++;
}else{//恢复开始的位置的下一个位置
i = i-j+1;
j = 0;
}
}
if(j >= pl) r = i-pl+1;
else r = -1;
return r;
}
void MChar::printStr(char* s){
if(!s) throw "串不能为空!\n";
while(*s != '\0') cout<<*s++<<" ";
cout<<endl;
}
const char* MChar::toUpper(char *s){
if(!s) throw "串不能为空!\n";
int l = 'a' - 'A';
cout<<l<<endl;
while(*s != '\0'){
if(*s>= 'a' && *s<='z') *s = *s - l;
s++;
}
return s;
}
//整数转换为字符串
void MChar::itoaTest(int num, char str[]){
int n = num, i, k;
char tmp[20];//假设不会发生溢出
if(num < 0) n = -n;
for(k=0; n>0; k++){
i = n % 10;
tmp[k] = i + '0';//'0'-->48, '0'+1==49-->'1'
n = n / 10;
}
//反向
if(num < 0) tmp[k] = '-';
else k--;
for(i=0; k >= 0; i++){
str[i] = tmp[k--];
}
str[i] = '\0';
}
//字符串转换成整数atoi函数(关键是注意,特殊字符的判断,前面的+-等)
/**注意四点:
*1.整数以谁开头,‘+’,‘-’或者空格,要判断;
*2.如果输入字符串是指针,首先判断是否为空;
*3.输入字符串可能含非数字字符,如果含果断结束;
*4.最后得到的整数特别大,可能溢出
*/
int MChar::atoiTest(char s[]){
int sign = 1, tmp = 0, i = 0;
//判断前面是否有空格,回车等
while(' '==s[i]||'\t'==s[i]) i++;
//符号判断
if(s[i]=='-'){
i++;
sign = -1;
}else if(s[i]=='+'){
i++;
sign = 1;
}
while(s[i] != '\0'){
//对于非数字,直接结束
if(s[i] < '0' || s[i] > '9') throw "含有非数字字符!";
//或者使用断言代替throw,不过throw更好,他能提供具体原因,这个可以自己指定,方便找到原因
//assert(s[i] >= '0'); assert(s[i]<= '9');
tmp = tmp*10 + s[i]-'0';
//处理溢出
if(tmp < 0) throw "整数过大溢出!";
//assert(tmp >= 0);
i++;
}
return sign*tmp;
}
//判断输入的是否是一个回文字符串
bool MChar::isPalindrome(char *s){
char input[100];
strcpy(input, s);
int length = strlen(input);
int begin = 0,end = length-1;
while(begin<end)
{
if(s[begin]==s[end]){
begin++;
end--;
}else{
break;
}
}
if(begin<end) return false;
else return true;
}
main.cpp
#include <iostream>
#include <cstring>
#include "mchar.h"
using namespace std;
int main(){
MChar mc;
char a[] = {'h','e','l','l','o','j','l','l','k','\0','o','o','o','o','o','o','o','o','o'};
char b[] = {'g','m','\0'};
char c[] = {'l','L','0','t','K','\0'};
try{
/*
mc.printStr(a);
cout<<"串长度:"<<mc.strLen(a)<<endl;
cout<<"串拷贝:";
char* s = new char[6];
mc.strCpy(s, c);
mc.printStr(s);
delete s;
cout<<"\n串连接:";
mc.strCat(a, b);
mc.printStr(a);
cout<<"\n子串截取:";
char* m = mc.subStr(a, 1, 4);
if(m) mc.printStr(a);
cout<<"\n串比较:";
cout<<mc.strCmp(c, a)<<endl;
cout<<"串插入:";
mc.strInsert(a, 7, b);
mc.printStr(a);
cout<<"串删除:";
mc.strDelete(a, 5, 7);
mc.printStr(a);
cout<<(int)'e'<<endl;
cout<<"查找字符:";
cout<<mc.findStr(a, 101)<<endl;
cout<<"子串位置:";
cout<<mc.strIndex(a, c)<<endl;
cout<<"大写转换:";
mc.toUpper(c);
mc.printStr(c);
cout<<"整数转换为字符串:";
char* t = new char[20];
mc.itoaTest(324344445, t);
mc.printStr(t);
cout<<(char)(3+'0')<<" "<<(int)'0'<<endl;//输出3 48
cout<<"字符串转换为整数:";
char t[] = {' ','-','3','4','5','2','9','\0'};
cout<<mc.atoiTest(t)<<endl;
cout<<'3'-'0'<<endl;
*/
cout<<"回文字符串判读:";
char s[20] ="1234554321";
if(mc.isPalindrome(s))
{
cout<<"True"<<endl;
}else{
cout<<"Fasle"<<endl;
}
}catch(char const *s){
cout<<s<<endl;
}
return 0;
}
3.几个操作
#include <iostream>
#include <cstring>
using namespace std;
bool isDigit(const char ch){
if(ch >= '0' && ch <= '9') return true;
return false;
}
//计算连续数字的个数,如ak123x5612393837?3043gef435,将其存入数组a中a[] = {123,56,123,43,43}
int countInt(const string s, string* result){
int count = 0; //查找到的字符串个数
int i=0,temp=11; //temp暂存,上一个数字(注:数字是从0~9故而这里设为11)
string str = ""; //临时存储,递增字符串(如123,54)
const char* c = s.c_str(); //转换为char数组
while(i < s.size()){
char a = c[i];
//-----------------循环处理连续数字字符串--------------------------------------
//判读是不是数字,如果是数字则要循环判段是否顺序递增或递减
while(isDigit(a)){
int k = a-'0';
if(str.size() == 0){ //1.如果刚开始,就直接添加到str
str.append(sizeof(char),a);
}else if(k == temp+1 || k == temp-1){ //2.如果不是第一个,而且是下一个数字,则添加到str
str.append(sizeof(char),a);
}else if(str.size() == 1){ //3.如果既不是第一个也不是连续的数组,置空并重新开始往str添加,注:顺序不能变,代表了判读的顺序
//restart again
str = "";
str.append(sizeof(char),a);
}else{ //4.如果str个数>1,而后面也没有连续的数字了,就放入result数组,并重新继续开始往str添加
*result++ = str;
count++;
//restart again
str = "";
str.append(sizeof(char),a);
}
a = c[++i];
if(!isDigit(a)){ //如果非数字,看是否满足放入result的条件,如果满足存入,否则跳出循环
if(str.size() > 1){
*result++ = str;
count++;
str = "";
temp = 11;
}
break;
}
temp = k;
}
i++;
}
return count;
}
//求最长重复子串
int longestString(const string str){
const char* s = str.c_str();
int n = str.size();
int index = 0, max = 0;
int length = 1, i=0,start=0;
while(i<n-1){
if(s[i] == s[i+1]){
length++;
}else{
if(max < length){
max = length;
index = start;
}
length = 1;
start = i;
}
i++;
}
cout<<"最长子串长度为:"<<max<<", 位置:"<<index+1<<endl;
return max;
}
bool isSign(const char ch){
if(ch == ',' || ch == '.' || ch == '?' || ch == '!' || ch == '"' || ch == '\'' || ch == '-' || ch == ' ') return true;
return false;
}
bool isSpicial(const char ch){
if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9')) return false;
return true;
}
//(文章的处理)将字符串中的特殊字符用空格代替(假设现在只含有,.?"!'-),若是多个空格,则用一个空格代替
void clearString(string str, char* result){
const char* s = str.c_str();
int len = str.size(), temp = 0;
for(int i=0; i<len; i++){
if(!isSpicial(s[i])){ //如果是字母或数字不处理
*result++ = s[i];
}else{
//如果是特殊字符则跳过
while(i<len && isSpicial(s[i])){
i++;
}
//特殊字符以空格取代
*result++ = ' ';
i--;//减去一个,因为for循环开始循环之前要i++
}
}
}
int main(){
/*
string s = "ak123x5612d393837?3043gef435";
string* a = new string[s.size()];
int count = countInt(s,a);
cout<<count<<endl;
for(int i=0; i<count; i++){
cout<<a[i]<<" ";
}
cout<<endl;
delete[] a;
//最长子串
string m = "4444fdasdfdrekkkkkkkkfdeeesfs";
longestString(m);
*/
string k = "What is it? she asked joyfully. Scarlett! 43 44 55ffg She was: Bitterly disappointed.";
char* result = new char[k.size()];
clearString(k, result);
for(int i=0; i<k.size(); i++){
cout<<result[i];
}
cout<<endl;
delete[] result;
return 0;
}