strrev函數

原型: char *strrev(char *s);
用法:#include <string.h>
功能:把字符串s的所有字符的順序顛倒過來(不包括空字符NULL)。
說明:返回指向顛倒順序後的字符串指針。
注意:這個函數直接使用時不能顛倒例如以下的內容:
char *forward="string";
很顯然這裏的"string"作爲常量放在常量區是不可修改的,而strrev函數的本質就是對forward指針指向的地址就行操作,所以編譯器會報錯。解決方法是用下面的方法進行初始化:
char forward[]="string";
這樣做將字符串以數組的方式存入棧,這時就可以利用該函數了。但是如何自己寫這個函數呢?簡單的思路就是創建一個函數,並傳入字符串的首地址,在函數內申請兩個指針,一個指向之字符串首地址,一個指向尾地址(爲什麼一定要這樣做呢?因爲希望直接利用字符串結尾的’\0‘,這樣就不用去考慮新建字符串後面如何+’\0‘的問題了),然後利用首尾斤進行數據交換,但是在嘗試直接交換後我得到了“string”的逆序,不是“gnirts”,而是“strrts”,道理很簡單,首先,首部的數據移到尾部時覆蓋了尾部的數據,第二,一開始是首部數據搬到尾部,但是到了後期就變成了逆序後的字符串尾部數據搬到首部,自然會出現上面的狀況。解決方法,第一,創建中間變量,在首部數據覆蓋尾部數據之前備份尾部數據;第二,在移動數據之前判斷是否到了中間位置。
貼上按照這個思路編寫的代碼:
char * mystrrev(char *p)
{
	char *p1;
	char *p2;
	char ch;
	static int i=0,j=0;
	p1=p;
	p2=p;	
	while(*(p1+i))
	{
		i++;
	}
	for(j=0;j<i;j++)
	{
		if((p1+i-1-j)>(p2+j))
		{			
			ch=*(p2+j);
			*(p2+j)=*(p1+i-1-j);
			*(p1+i-1-j)=ch;
		}		
	}
	return p2;
}

在編寫是沒有注意應該有p2=p;導致在一開始運行的時候編譯器死機,原因在於未聲明char *p;作爲定義並未聲明,這時候在解引用的時候相當於使用了野指針,自然會報錯,正確的使用方法是在初始化同時聲明,或者像上面的代碼裏,初始化爲NULL,雖然初始化爲NULL,在後面粗心直接解引用後果是出現段錯誤(segmentation fault),但是這是個絕對不可用的地址,不會造成太大的損失。
以上代碼雖然可以實現srerev函數的功能,但是效率卻大打折扣,因此改善如下。
char * mystrrev(char* p)  
{  
    char *p1=p;      
    char *p2=p;  
    char ch;  
    while(*p1++);  
    p1--;    
    p1--;    
   
    while(p2 < p1)  
    {  
        ch = *p2;  
        *p2++ = *p1;   
        *p1-- = ch;   
    }  
  
    return(p);  
}  
這裏的第一個p1--的目的是消除上面最近一個p1++的效果(++在後,後使用),第二個是跳過'\0‘。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章