/* memcpy ——— 拷貝不重疊的內存塊 */
void memcpy(void* pvTo, void* pvFrom, size_t size)
{
void* pbTo = (byte*)pvTo;
void* pbFrom = (byte*)pvFrom;
ASSERT(pvTo != NULL && pvFrom != NULL); //檢查輸入指針的有效性
ASSERT(pbTo>=pbFrom+size || pbFrom>=pbTo+size);//檢查兩個指針指向的內存是否重疊
while(size–>0)
*pbTo++ == *pbFrom++;
return(pvTo);
}
原文來自:http://blog.sina.com.cn/s/blog_6d041c110100mmc3.html
看的時候發現,有的算法很有技巧性,於是自己就添加了註釋,希望我下次看的時候能有收穫!
1)寫出在母串中查找子串出現次數的代碼.
int count1(char* str,char* s)
{
char* s1;
char* s2;
int count = 0;
while(*str!=’\0′)
{
s1 = str;
s2 = s;
while(*s2 == *s1&&(*s2!=’\0′)&&(*s1!=’\0′))
{
s2++;
s1++;
}
if(*s2 == ‘\0’)
count++; //經過了綠色的步驟,一定是找到了一個匹配的字符串。
str++;
}
return count;
}
2)查找第一個匹配子串位置,如果返回的是s1長度len1表示沒有找到
size_t find(char* s1,char* s2)
{
size_t i=0;
size_t len1 = strlen(s1);
size_t len2 = strlen(s2);
if(len1-len2<0) return len1;
for(;i<len1-len2;i++)
{
size_t m = i; //m是用來記錄對比中s1向前走的位置。
for(size_t j=0;j<len2;j++)
{
if(s1[m]!=s2[j]) //當不是匹配字符時
break;
m++; //爲下一次匹配做準備。
}
if(j==len2) //要使得j == len2,則上面的for應該完成,所以此時已經找到第一個匹配的位置,所以要跳出。
break;
}
return i<len1-len2?i:len1;
}
strstr的實現:
const char * _strstr(const char *src, const char *needle)
{
const char *p1, *p2;
p1 = src;
p2 = needle;
while (*src != ‘\0’ && *needle != ‘\0’)
{
if (*src++ != *needle++){ //這次判斷,非常重要,如果不成立,src和needle都子增加了,如果成立,那麼needle要從頭開始,但是被搜搜索的字符
//要從下一個字符開始!!
needle = p2; //要從頭開始
src = ++p1; //從下一個字符開始搜索needle
}
}
if (*needle == ‘\0’)
return p1;
return NULL;
}
3)實現strcpy函數
char *my_strcpy(char *destination, const char *source)
{
assert(destination!=NULL&&source!=NULL);
char* target = destination;
while((*destination++ = *source++) != ‘\0’);
return target ;
}
此函數原型爲 char *strcat(char *dest, const char *src).
功能爲連接兩個字符串,把src連接到dest後面;返回dest地址
實現如下
區別於strcat
char * strcat(char *dest,const char *src)
{
char* addr=dest;
while(*dest)//找到’\0′
{
dest++;
};
while(*dest++=*src++)
{};
return addr;
}
出現次數相當頻繁
4)實現strcmp函數
int strcmp11(char* l,char* r)
{
assert(l!=0&&r!=0);
while(*l == *r &&*l != ‘\0’) l++,r++;
if(*l > *r) //此時*l和*r不相等!!!
return 1;
else if(*l == *r)
return 0;
return -1;
}
5) 實現字符串翻轉
void my_reserve(char* str)
{
//assert(str != NULL);
char * p1 = str; //第一個字符
char * p2 = str-1;
while(*++p2); //一般要求不能使用strlen
p2 -= 1; //p2指向最後一個字符
while(p1<p2)
{
char c = *p1; //保留前部分
*p1++ = *p2;
*p2– = c;
}
}
6)、用指針的方法,將字符串“ABCD1234efgh”前後對調顯示
//不要用strlen求字符串長度,這樣就沒分了
代碼如下:
char str123[] = “ABCD1234efgh”;
char * p1 = str123;
char * p2 = str123-1;
while(*++p2);
p2 -= 1;
while(p1<p2)
{
char c = *p1;
*p1++ = *p2;
*p2– = c;
}
7) 給定字符串A和B,輸出A和B中的最大公共子串。比如A=”aocdfe” B=”pmcdfa” 則輸出”cdf”
#i nclude<stdio.h>
#i nclude<stdlib.h>
#i nclude<string.h>
char *commanstring(char shortstring[], char longstring[]) //傳入是可以隨便,然後再計算大小,大的賦值給long,小的賦值給short
{
int i, j;
char *substring=malloc(256);
if(strstr(longstring, shortstring)!=NULL) //如果……,那麼返回shortstring
return shortstring;
for(i=strlen(shortstring)-1;i>0; i–) //否則,開始循環計算
{
for(j=0; j<=strlen(shortstring)-i; j++)
{
memcpy(substring, &shortstring[j], i); //先從最大子串開始搜索,然後再逐漸使字串變短!!
substring[i]=’\0′;
if(strstr(longstring, substring)!=NULL)
return substring;
}
}
return NULL;
}
main()
{
char *str1=malloc(256);
char *str2=malloc(256);
char *comman=NULL;
gets(str1);
gets(str2);
if(strlen(str1)>strlen(str2)) //將短的字符串放前面
comman=commanstring(str2, str1);
else
comman=commanstring(str1, str2);
printf(“the longest comman string is: %s\n”, comman);
}
8) 判斷一個字符串是不是迴文
int IsReverseStr(char *str)
{
int i,j;
int found=1;
if(str==NULL)
return -1;
char* p = str-1;
while(*++p!= ‘\0’);
–p;
while(*str==*p&&str<p) str++,p–;
if(str < p)
found = 0;
return found;
}
9)寫函數完成內存的拷貝
void* memcpy( void *dst, const void *src, unsigned int len )
{
register char *d;
register char *s;
if (len == 0)
return dst;
if ( dst > src ) //考慮覆蓋情況
{
d = (char *)dst + len – 1;
s = (char *)src + len – 1;
while ( len >= 4 ) //循環展開,提高執行效率
{
*d– = *s–;
*d– = *s–;
*d– = *s–;
*d– = *s–;
len -= 4;
}
while ( len– )
{
*d– = *s–;
}
}
else if ( dst < src )
{
d = (char *)dst;
s = (char *)src;
while ( len >= 4 )
{
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
*d++ = *s++;
len -= 4;
}
while ( len– )
{
*d++ = *s++;
}
}
return dst;
}
10)寫一個函數,它的原形是int continumax(char *outputstr,char *intputstr)
功能:
在字符串中找出連續最長的數字串,並把這個串的長度返回,並把這個最長數字串付給其中一個函數參數outputstr所指內存。例如:”abcd12345ed125ss123456789″的首地址傳給intputstr後,函數將返回
9,outputstr所指的值爲123456789
int continumax(char *outputstr, char *inputstr)
{
char *in = inputstr, *out = outputstr, *temp, *final;
int count = 0, maxlen = 0;
while( *in != ‘\0’ )
{
if( *in > 47 && *in < 58 )
{
for(temp = in; *in > 47 && *in < 58 ; in++ )
count++;
}
else
in++;
if( maxlen < count )
{
maxlen = count;
count = 0;
final = temp;
}
}
for(int i = 0; i < maxlen; i++)
{
*out = *final;
out++;
final++;
}
*out = ‘\0’;
return maxlen;
}
11) 編寫一個 C 函數,該函數在一個字符串中找到可能的最長的子字符串,且該字符串是由同一字符組成的。
主要思想就是:定義兩個臨時變量,iTemp來存儲每次找到的子字符串的大小, cpTemp來存儲從什麼位置開始搜索!!
char * search(char *cpSource, char ch)
{
char *cpTemp=NULL, *cpDest=NULL;
int iTemp, iCount=0;
while(*cpSource)
{
if(*cpSource == ch)
{
iTemp = 0;
cpTemp = cpSource;
while(*cpSource == ch) //找到了可能是最長的一次匹配
++iTemp, ++cpSource;
if(iTemp > iCount)
iCount = iTemp, cpDest = cpTemp;
if(!*cpSource) // 當!0爲真是退出,即*(cpSource)到了尾部
break;
}
++cpSource;
}
return cpDest;
}