原型: char *strrev(char *s);
用法:#include <string.h>
功能:把字符串s的所有字符的順序顛倒過來(不包括空字符NULL)。
說明:返回指向顛倒順序後的字符串指針。
注意:這個函數直接使用時不能顛倒例如以下的內容:
很顯然這裏的"string"作爲常量放在常量區是不可修改的,而strrev函數的本質就是對forward指針指向的地址就行操作,所以編譯器會報錯。解決方法是用下面的方法進行初始化:
這樣做將字符串以數組的方式存入棧,這時就可以利用該函數了。但是如何自己寫這個函數呢?簡單的思路就是創建一個函數,並傳入字符串的首地址,在函數內申請兩個指針,一個指向之字符串首地址,一個指向尾地址(爲什麼一定要這樣做呢?因爲希望直接利用字符串結尾的’\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‘。