分享

字符串处理

 learnandup 2012-03-09
字符串处理
TAG:程序设计思想及范例,字符串处理
TEXT:
字符串处理问题是C语言编程中经常遇到的问题。熟练的掌握字符串处理的方法,可以增强对字符串的存贮及其处理方法的理解,写出高效的计算机程序。字符串处理问题的实质是一维char型数组的处理问题。需要特别注意字符串的结束符'\0'。

编写函数mystrcat,实现和strcat完全相同的功能。
首先确定mystrcat函数的输入和输出。函数输入是两个字符串;输出是一个连接后的字符串;函数没有返回值。函数参数是两个char型数组的指针。函数头可以写成void mystrcat(char chStr1[],char chStr2[]),或者void mystrcat(char *psz1,char *psz2)。
函数内部的算法:可以先计算字符串1的长度,从字符串1的长度+1位置(也就是字符串1结束符的位置)开始,利用循环依次将字符串2的所有字符拷贝到字符串1。遍历字符串元素时,可以利用字符串结束符结束循环。
拷贝过程结束后,要确保连接后的字符串有字符串结束符,否则会产生错误。
void mystrcat(char chStr1[],char chStr2[])
{
int i,j;
/*计算chStr1的长度,循环结束后i的值等于chStr1的长度加1*/
for(i=0; chStr1[i]!='\0';i++);
/*在chStr1后添加chStr2的每个字符*/
for(j=0; chStr2[j]!='\0';j++)
chStr1[i+j]= chStr2[j];
/*最后一定要加上字符串结束符*/
chStr1[i+j]='\0';
}
main()
{
/*定义两个字符数组s1和s2,注意s1要足够大,可以容纳连接后的字符串*/
char s1[50],s2[50];
/*输入s1和s2*/
printf("\nPlease input s1:\n");
gets(s1);
printf("Please input s2:\n");
gets(s2);
/*调用函数进行处理*/
mystrcat(s1,s2);
/*打印输出结果*/
printf("Catenated s1=%s",s1);
}
结果为:
Please input s1:
hello!
Please input s2:
kitty
Catenated s1=hello!kitty
如果使用指针方式,函数mystrcat可以写得更简练一些,下面是使用指针的一个例子(main函数可以不做改动):
void mystrcat(char *psz1,char *psz2)
{
/*将指针psz1拨到字符串末尾*/
while(*psz1) psz1++;
/*在psz1后添加psz2的每个字符,注意循环最后一次拷贝了'\0'*/
while(*psz1++=*psz2++);
}


编写函数,输入一个整数,将其转换为字符串输出。例如,输入整数86556,输出字符串"86556"。
首先确定函数头,函数输入一个long型整数,输出一个char型字符数组,因此可以定为void long2string(long lNum,char chWord[])。注意这里的整数可能比较大,不要定为int型。
函数中,可以首先利用循环和%和/运算符,依次取得整数的每个位。思路如下:例如86556,我们可以将其对10取余,得到个位6;将86556除10余8655,继续对10取余,得到十位5;… … 以此类推,直到该数变为0为止。这样就可以将整数的每个位分离出来。
在上述的循环过程中,将分离出的数字依次保存到字符数组中。但是要注意,字符数组中保存的是字符,是数字的ASCII码,而不是数字本身的值。因为ASCII码表中阿拉伯数字的码值是连续的,因此一个常用的技巧是,字符0加数字值即为该数字的ASCII码值。
上述过程结束后,字符数组里存放了整数的每个位,但是不符合题目的要求,顺序正好相反。这可以用一个循环对数组进行转置:字符串第一个元素和最后一个元素对换;第二个元素和倒数第二个元素对换;… …程序循环进行 字符串长度/2 次(如果字符串长度为奇数,中间元素正好不用处理)。
void long2string(long lNum,char chWord[])
{
int i=0,j;
char chTemp;
/*依次取整数的末位,存入chWord */
while(lNum!=0)
{
chWord[i]='0'+lNum%10;/*转换为数字的ASCII码*/
i++;
lNum=lNum/10;
}
/*字符串最后一位加'\0'*/
chWord[i]='\0';
/*将字符串转置*/
for(j=0;j<i/2;j++)
{
chTemp=chWord[j];
chWord[j]=chWord[i-1-j];
chWord[i-1-j]=chTemp;
}
}
main()
{
/* lNum是输入的整数,chWord是转换后的字符串*/
long lNum;
char chWord[50];
/*输入一个整数*/
printf("\nPlease input a integer:\n");
scanf("%ld",&lNum);
/*调用函数进行处理*/
long2string(lNum,chWord);
/*打印输出结果*/
printf("The outputed string=%s",chWord);
}
运行结果为:
Please input a integer:
1972
The outputed string=1972
函数long2string也可以使用递归函数实现,下面是使用递归和指针的一个例子(main函数可以不做改动):
void long2string(long lNum,char *pszWord)
{
/*如果lNum等于0,不用继续递归*/
if(lNum==0)
{
/*字符数组的第一个单元是字符串结束符,后续的过程
要根据它添加整数的位*/
*pszWord='\0';
return;
}
/*先递归处理lNum前面的位*/
long2string(lNum/10,pszWord);
/*再将lNum的最后一位添加到字符串后*/
while(*pszWord) pszWord++;
*pszWord++='0'+lNum%10;
*pszWord='\0'; /*不要忘记处理字符串结束符*/
}

输入三个字符串,将字符串1中所有与字符串2相同的子串替换成字符串3。例如,输入的字符串1为"werLOOPouyio3o565p6 LOOPedd",字符串2为"LOOP",字符串3为"NEW",那么替换后,字符串1为"werNEWouyio3o565p6NEWedd"。
根据题意,写一个符合要求的函数头。函数有两个char型数组指针的输入参数,一个char型数组指针输出参数,没有返回值。可以定为void replace(char chString[],char chOldWord[],char chNewWord[]),参数分别代表字符串1,字符串2和字符串3。
我们可以分析实现一次替换的算法。可以分解为3个步骤:查找、调整长度和替换。
步骤1:查找字符串1中是否有字符串2。利用循环可以得到字符串2的长度nLen2。从字符串1的第一个元素开始,比较后面的nLen2个元素是否和字符串2的nLen2个元素完全相同。如果完全相同,则进行步骤2;否则从字符串1的第二个元素开始,继续上述过程… …。如果搜索到字符串末尾也不能进行步骤2,则说明字符串1中没有字符串2。
步骤2:计算替换后的字符串1长度,调整字符串1。假设字符串1的位置nStartPos后的nLen2个元素与字符串2相同。如果字符串3的长度nLen3大于字符串2的长度nLen2,那么字符串1的位置nStartPos+nLen2后的所有元素向后移动nLen3–nLen2位;否则,向前移动nLen2–nLen3位。这样处理后,字符串1中不需要替换的部分已经调整完毕。
步骤3:利用循环,把字符串1的位置nStartPos后的nLen3个元素换成字符串3。
替换字符串1中的所有字符串2,可以利用循环对上述算法作适当扩展即可。每次替换总是从新的nStartPos位置开始进行。但是一定要注意,每次替换后字符串1的长度可能发生变化,nLen1每次要重新计算。
void replace(char chString[],char chOldWord[],char chNewWord[])
{
int i,nStartPos=0,nLen1=0,nLen2=0,nLen3=0,nFound;
/*计算旧词和新词的长度*/
while(chOldWord[nLen2++]!='\0');
nLen2--;
while(chNewWord[nLen3++]!='\0');
nLen3--;
/* chString中可能有多个旧词,均要替换为新词;
利用循环向前拨动查找位置,逐次进行比较和替换*/
while(chString[nStartPos]!='\0')
{
/*从nStartPos位置开始,Len2长度的字符串是否和旧词相同?*/
nFound=1;
for(i=0;i<nLen2;i++)
if(chString[nStartPos+i]!=chOldWord[i])
{
nFound=0;
break;
}
if(nFound==1)/*相同,这Len2个字符需要被替换掉*/
{
/*计算输入字串chString 的长度,注意在循环中每次计算chString
长度是必要的,因为完成一次替换后,chString的长度可能发生变化*/
while(chString[nLen1++]!='\0');
nLen1--;
/*新词、旧词长度可能不同,先将chString长度调至正确的位置,
chString中nStartPos 后的字符可能需要前移或后移若干位*/
if(nLen3-nLen2>=0)/*新词比旧词长,从后向前移动*/
{
for(i=nLen1-1;i>=nStartPos;i--)
chString[i+nLen3-nLen2]=chString[i];
}
else/*新词比旧词短,从前向后移动*/
{
for(i=nStartPos+nLen2;i<nLen1;i++)
chString[i+nLen3-nLen2]=chString[i];
}
chString[nLen1+nLen3-nLen2]='\0';
/*将新词复制到chString,替换原来的旧词 */
for(i=0;i<nLen3;i++)
chString[nStartPos+i]=chNewWord[i];
/*下一次检查的位置:从替换后新词后面的位置开始*/
nStartPos+=nLen3;
}
else/*不同,则从下一个字符开始,继续进行检查*/
nStartPos++;
}
}

main()
{
char chStr[100],chOld[100],chNew[100];
/*输入原始字符串、被替换串和替换串*/
printf("\nPlease input the original string:\n");
gets(chStr);
printf("Please input the word to be replaced:\n");
gets(chOld);
printf("Please input the new word to replace:\n");
gets(chNew);
/*调用函数进行替换*/
replace(chStr,chOld,chNew);
/*输出结果*/
printf("The processed string = %s",chStr);
}
程序运行结果如下:
Please input the original string:
Tom want to go to school, Tom's father said...
Please input the word to be replaced:
Tom
Please input the new word to replace:
Jimmy
The processed string = Jimmy want to go to school, Jimmy's father said...
函数replace也可以使用递归函数实现,下面是使用递归和指针的一个例子(main函数可以不做改动)。
#include "stdio.h"
void replace(char *pszString,char *pszOldWord,char *pszNewWord)
{
int i,nLenOld=0, nLenNew=0;
char *pszPos;
/*计算旧词和新词的长度*/
while(*(pszOldWord+nLenOld)) nLenOld++;
while(*(pszNewWord+nLenNew)) nLenNew++;
/*从当前指针pszString开始查找并替换一个旧词*/
while(*pszString!='\0')
{
/*从当前位置开始查找,如果找到,pszPos为 pszString前移nLenOld 长度*/
pszPos=pszString;
for(i=0;i<nLenOld;i++)
{
if(*(pszOldWord+i)!=*pszPos)
{
pszPos=NULL;
break;
}
pszPos++;
}
if(pszPos!=NULL)/*找到了,进行替换*/
{
if(nLenNew<nLenOld) /*新词比旧词短,从前向后移动*/
{
while(1)
{
*(pszPos-nLenOld+nLenNew)=*pszPos;
if(*pszPos++=='\0')
break;
}
}
else if(nLenNew>nLenOld) /*新词比旧词长,从后向前移动*/
{
while(*pszPos++);
while(pszPos>=pszString+nLenOld)
{
*(pszPos-nLenOld+nLenNew)=*pszPos;
pszPos--;
}
}

/*将新词复制到chString,替换原来的旧词*/
for(i=0;i<nLenNew;i++)
*pszString++=*(pszNewWord+i);
break;
}
else/*找不到,继续下一个位置*/
pszString++;
}

/*在替换过的字符串中,递归替换下一个字符串*/
if(*pszString)
replace(pszString,pszOldWord,pszNewWord);
}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多