前言:
笔试题基本上必考题之一:字符串的处理,涉及到指针、数组、以及字符串数组;近几日的笔试字符串处理让我无从下手,因此根据近几日的笔试题,总结了一波常见的操作;
1.整数与字符数字互换类型:
void char_to_int( char *buf, int *num,int size) //字符串换成数字
{
int i = 0;
int temp = *num;
if( buf == NULL || num == NULL || size <=0)
{
printf("Error:error arg\n");
return ;
}
while( buf[i] != 0 ) //遍历跳出条件:当碰到0退出循环就是'\0'=0
{
temp = temp*10 + (buf[i] - '0'); //利用字符减字符的ASCII值获得int类型值后,通过累乘10来表示十进制当中的个、十、百位;
i++;
}
*num = temp;
}
void int_to_char( int num,char *buf,int size) //数字换成字符串
{
int i = 0,j = 0;
char temp[size];
while(num) //遍历跳出条件:判断数字是否为0
{
temp[i] = num%10 +'0'; //对各个位进行取余,从而取得各个位上0~9的数值,在通过加上字符'0'的ASCII值进行相加,化成对应'0'~'9'的ASCII值
i++;
num = num/10; //获取个、十、百位
}
temp[i] = 0; //当跳出循环时,字符串必须以\0结尾,而0 = '\0',并且到这里时这个字符串是逆序的,需要调整为正序;
while(i >= 0) //调为正序
{
buf[j] = temp[i-1];
j++;
i--;
}
buf[j] = 0; //同样给字符串进行结尾
}
注:需要强调的是,函数传参是按值传递,所以你想保存则需要指针的协助,让其按地址传递;或者,可以通过函数的返回值来存储到相应的函数区;
注:这个例题可以辅助剑指offer里面的面试案例(关于字符串转换)一起食用,效果更佳;
2.字符串复制函数问题:
功能:将src所指向的字符串覆盖到dest所指向的字符串:比如,src:123 dest:12 返回12
char *strcopy(char *dest, const char *src)
{
if( dest == NULL || src == NULL )
{
printf("Error:error arg\n");
return NULL;
}
while( *dest != 0 || *src != 0 ) //
{
*(dest++) = *(src++); //变量之间赋值,并且表示字符串个个字符;
}
*dest = 0;
return dest;
}
3.strstr()函数的实现:
功能介绍:strstr()函数是把主串中的字串及以后的字符全部返回:比如,主串:1234,字串是23,则返回234;
char *strstr1(char *string,const char *strCharSet) //在主串中寻找字串
{
int i;
int j;
int temp;
if( string == NULL || strCharSet == NULL )
{
printf("Error:error arg\n");
return NULL;
}
for( i = 0 ; string[i] != '\0'; i++) //在主串中进行遍历,遇到'\0'退出循环
{
j = 0;
temp = i; //用于保存i的位置
if(string[i] == strCharSet[j]) //主串的第一个字符和子串的第一个字符进行匹配
{
while(string[i++] == strCharSet[j++]) //第一个字符匹配成功后,继续匹配下去
{
if((strCharSet[j] == '\0')) //直到字串遇到结束符
return &string[i-j]; //要求返回的是与子字串相同的第一个字符起的主串地址;
}
i = temp; //下一个字符不匹配则返回,并且回到刚刚的位置;
}
}
return NULL;
}
4.实现strcat()函数
功能介绍:连接两个字符串并连接好后的字符串保存在第一个字符串当中;
char *strcat1(char *dest,char *src)
{
char *p = dest; //利用指针的作用
if( dest == NULL || src == NULL )
{
printf("Error:error arg\n");
return NULL;
}
while( *p != 0 ) //不对原来的字符串进行操作,但需要知道末尾位置;
{
p++;
}
while((*p++ = *src++)!= 0 ); 与strcpy核心语句操作相同;
return dest;
}
注:如果char arr[8]; 则 *arr++可以用来遍历字符串,而(*arr)++则表示第一个字符串的字符+1 'h' -> 'i';arr[1~7]代表变量,如果要取地址,则&arr[1~7];
5.字符串操作之快慢指针:
功能介绍:
使用快慢指针好处在于:函数体不要额外分配数组空间;
快慢指针用法很多,快指针用于查找特定的字符,然后用来覆盖慢指针指向的地址上的值;
例1:在字符串str1中删除str2字符串中出现的字符,如:str1:abcaaa str2: ac 输出结果为:str1:b
快指针:pfast指向str1,用来查找不需要删除的字符;
慢指针:pslow指向str1,用于存放快指针找到的字符;
找到不需要的删除的字符,进行如下操作:
*pslow++=*pfast++;
找到需要删除的字符,进行如下操作:
pfast++;
void Delete_str(char *str1,char *str2)
{
char *pfast=str1;
char *pslow=str1;
char *p2=str2;
if(str1 == NULL || str2 == NULL)
{
printf("Error:arg error!\n");
return;
}
while(*p2 != 0) //指针p2从str2的第一个字符开始在字符串str1进行匹配,如果使用哈希表则时间复杂度要低也快,想实现自行百度;
{
while(*pfast != 0) //用快指针进行遍历,本层循环结束条件为:快指针在遍历完一次字符串str1
{
if(*pfast != *p2) //不匹配的字符操作
{
*pslow = *pfast;
pslow++;
}
pfast++; //剩下的都是匹配字符的操作
}
*pslow = *pfast; //遍历完一次后,重新指向
pslow = str1; //遍历完一次后,重新指向
pfast = str1; //遍历完一次后,重新指向
p2++; //遍历完一次后,p2向下一个地址移动;
}
*pslow = *pfast; //此时*pfast为'\0'赋值给*pslow进行结尾;
}
例2:合并字符串间连续多个空格如输入:___a___b__c___(其中"_"表示空格)输出结果为:a_b_c
同样使用快慢指针来操作:
快指针:用于查找小写字母的字符;
慢指针:用于覆盖当前地址上的字符;
找到非空格字符的操作:
*pslow++=*pfast++;
找到空格字符的操作:
*pslow++=*pfast++;
for(;*pfast == ' '; pfast++);
int main()
{
char str[100];
char *pfast = str;
char *pslow = str;
printf("pfastlease inpfastut strings:");
gets(str);
while(*pfast == ' ') //忽略非空字符前面的空格字符;
{
pfast++;
}
while(*pfast != 0) //遍历str1直到/0
{
if((*pfast >= 'a' && *pfast <= 'z')) //不是空格字符的操作;
{
*pslow++=*pfast++;
}
else //空格字符的操作;
{
*pslow++ = *pfast++;
for(;*pfast == ' ' ;pfast++);
}
}
if(*(pslow-1) == ' ') //快指针指向最后一个字符后面有空格
{
*(pslow-1) = 0;
}
else //快指针指向最后一个字符后面没有空格
{
*pslow = 0;
}
printf("str =%s\n",str);
return 0;
}
变式:
将字符串中,字符首和尾的空格去掉去掉:
int remove_blank(char *str)
{
char *s=str;
char *p=str;
if( !str || strlen(str)<=0 )
return -1;
/* find the first character is not blank from head */
while( *s!='\0' && isblank(*s) )
{
s++;
}
/* copy the left characters to string head */
while(*s!='\0')
*p++=*s++;
/* end of '\0' */
*p='\0';
/* find end character position */
s = &str[strlen(str)-1];
/* find all the end blank character */
while( isblank(*s) )
{
s--;
}
*(s+1) = '\0';
return 0;
}
6.字符串逆序操作:比如:abcd 输出为dcba
有两种方法实现字符串逆序:
-
使用首尾交换的方式进行逆序;
-
分配新空间操作;
笔试通常是第一种情况,甚至不让你使用字符串处理函数;
定义2个变量,分别为i和j,其中i用来从字符串头开始向尾部遍历,j从尾部开始向首部遍历,循环结束条件为i<=j (其中<的情况为字符串的字符为偶数个,=为奇数个)
void nixuString(char * str)
{
int i = 0,j = 0;
char temp;
char *Sp = str;
while(*Sp != '\0') //计算字符串长度
{
j++;
Sp++;
}
j=j-1; //算上了\0需要-1
while(i <= j) //其中<的情况为字符串的字符为偶数个,=为奇数个
{
temp = str[i]; //交换
str[i] = str[j];
str[j] = temp;
i++;
j--;
}
printf("str:%s\n",str);
}
main函数实现体:
char_to_int()、int_to_char()函数在main函数的调用用例;
int main()
{
int num = 12345;
int temp_num = 0;
char temp_str[7];
char str[7] = {'1','2','3','4','5'};
#if 1
int_to_char(num,temp_str,7);
printf("str:%s\n",temp_str);
#endif
#if 0
char_to_int(str,&temp_num,7);
printf("str:%d\n",temp_num);
#endif
7.字符串循环移位包含操作:
给定两个字符串s1,s2,要求判断s2能否被s1循环移位得到的字符串包含。
例如给定s1="AABCD"和s2="CDAA“,返回true ;给定s1="ABCD"和s2="ACBD",返回false。
实现函数bool_cyc_shift(char *s1,char *s2)函数
/*********************************************************************************
* Copyright: (C) 2018 Guo Zhihao
* All rights reserved.
*
* Filename: xunhuanweiyi.c
* Description: 字符串移位循环 返回值:符合条件:ture,不符合条件false
*
* Version: 1.0.0(10/15/2018)
* Author: Guo Zhihao <810170156@qq.com>
* ChangeLog: 1, Release initial version on "10/15/2018 06:40:09 PM"
*
********************************************************************************/
#include<stdio.h>
#include<stdbool.h>
#include<string.h>
bool bool_cyc_shift(char *s1,char *s2,int len1,int len2) //字符串s1,s2,以及对应的长度len1,len2
{
int i;
if(s1 == NULL || s2 == NULL || len1 < len2) //判断传参
return false;
for(i=0;i<len1;i++)
{
int j = 0;
for(;j<len2;j++)
{
if(s2[j] != s1[(i+j)%len1]) //移位循环匹配字符
break;
}
if( j == len2 ) //符合条件为:遍历完s2,否则不符合条件则会先遍历完s1;
return true;
}
return false;
}
int main()
{
char s1[] = "AABCD";
char s2[] = "CDAA";
bool result;
int len1 = strlen(s1);
int len2 = strlen(s2);
result = bool_cyc_shift(s1,s2,len1,len2);
printf("result = %d\n",result);
return 0;
}