2010-02-04 59 views
3

我想用指針來反轉C++中的char數組。我想知道是否有什麼我應該做的不同?我是否正確地做這件事?有沒有更有效的方法來實現這一點?反向C風格字符串? - C++

我的小程序:

int main () 
{ 
    char buffer[80]; 

    PrintHeader(); 

    cout << "\nString reversal program"; 
    cout << "\nType in a short string of words."; 
    cout << "\nI will reverse them."; 
    cout << "\n:"; 
    cin.getline(buffer, 79); 

    cout << "\nYou typed " << buffer; 
    reverse (buffer); 
    cout << "\nReversed: " << buffer; 

    cout << endl; 
    system("PAUSE"); 
    return 0; 

} 


void reverse(char* string) 
{ 
    char* pStart, *pEnd; 
    int length; 
    char temp; 

    length = strlen(string); 

    pStart = string; 
    pEnd = &string[length - 1]; 

    while(pStart < pEnd) 
    { 
     temp = *pStart; 
     *pStart = *pEnd; 
     *pEnd = temp; 
     pStart++; 
     pEnd--; 
    } 
} 
+1

我在面試時遇到了同樣的問題。 – Void

+0

我敢肯定這個問題是一個騙局: http://stackoverflow.com/questions/784417/reversing-a-string-in-c http://stackoverflow.com/questions/2124600/how-to-反向字符串就地使用指針 –

回答

9
void str_reverse(char *str) { 
    char *str_end = strchr(str, 0); 
    std::reverse(str, str_end); 
} 

如果你應該寫一個循環,

void str_reverse(char *str) { 
    std::size_t len = std::strlen(str); 
    for (std::size_t index = 0; index != len/2; ++ index) { 
     std::swap(str[ index ], str[ len - index - 1 ]); 
    } 
} 

或者,當然,如果你能使用C++字符串,

void str_reverse(std::string &str) { 
    std::reverse(str.begin(), str.end()); 
} 
+0

您的循環代碼(第二個)在交換字符時會導致訪問衝突。我在Visual Studio中測試了它。 str是字符串,所以我不認爲你可以修改它。 –

+0

@erolyeniaras您的代碼添加了字符串文字。在這個問題或這個答案中沒有這樣的東西。 – Potatoswatter

+0

第二種解決方案出現錯誤:拋出異常:寫訪問衝突。 _Left是0xC2F490。 如果有這種異常的處理程序,程序可能會安全地繼續。 – user2286810

1

你可以使用std::swap(*pStart, *pEnd)而不是開放式編碼掉。

哎呀,你可以使用std::reverse(buffer, buffer + strlen(buffer))。但我想這不會真的使用指針自己,並給出這個要求,它看起來很好。

嗯,實際上,一個小小的尼特:如果length==0,然後&string[length - 1]沒有指向字符數組,並且理論上不是一個有效的指針。

0

真的沒什麼錯你我會遠離使用衆所周知的類型名稱作爲字符串等變量,因爲它會讓其他人閱讀時感到困惑。只是爲了更多的方式,你可以做到這一點。

void RevBuff(char* Buffer) 
{ 

int length = strlen(Buffer); 
char * CpBuff = _strdup(Buffer); 
for(int i = length -1, x = 0; i >=0 ; i--, x++) 
{ 
    Buffer[x] = CpBuff[i]; 
} 
free(CpBuff); 
} 

但是像上面說你幾乎總是要使用的庫函數在你自己的代碼,如果你能找到一個(你不知道有多少次我看到專業的程序員在編寫中存在的標準碼庫時,它可以很容易地被發現了谷歌搜索,但我離題。

3

假設你不能使用任何東西,但C字符串函數,我會

  • 避免預先聲明變量之初函數,這是一個需求nt(與1990年的標準一致),但在C++中,聲明並初始化變量在哪裏使用它們更爲習慣。

  • 如果字符串爲空,請避免超出範圍(遞減範圍超出字符串的起始處)。

因此,像:

void reverse(char* string) 
{ 
    char* first = string; 
    char* last = string + strlen(string); 

    while(first < last) 
    { 
     --last; //avoids decrementing last beyond start of string if string is empty 
     char temp = *first; 
     *first = *last; 
     *last = temp; 
     ++first; 
    } 
} 
+0

我收到錯誤消息:引發異常:寫訪問衝突。 首先是0x137F490。 如果有這種異常的處理程序,程序可能會安全地繼續。 – user2286810

0

你的代碼是非常詳細,並列舉每個操作,就像在撿字符串的長度或字符串的結尾分配指針或使用一個輔助變量交換價值。

有很多方法可以使其更有效(正如其他答案所證明的那樣),但可以說更準確。您的解決方案將代碼清晰地提前於性能,這是一種值得讚揚的習慣。

當然,代碼可以用一半的指令編寫,但是優化編譯器會完成與你的代碼幾乎相同的工作(可以通過一些聰明的編碼來減少幾個循環),但是你的代碼更易讀。

當然,如果你真的想要一些極端的性能提升(但是在更長的字符串上,可能是兆字節的數據),這對於GPU來說是一個完美的工作。它將使用50倍的時間來設置操作,然後是當前CPU時間的一小部分來執行操作。

+0

我不認爲指令和輔助變量的計數直接映射到執行時間(優化編譯器可能最有可能將其刪除並重新排列)。 – visitor

+0

@visitor:是的。優化編譯器有時會與過於冗長的代碼混淆,而無法猜測作者的意思 - >未能優化它。儘管這並不是一個規則,過於簡潔的代碼可能會讓優化器產生混淆。只有擁有大量的技能和知識,您才能編寫比優化程序更優化的代碼。所以沒有必要在這裏手工優化這個代碼,因爲你會變得更糟糕,而不是讓它清晰,明顯和簡單。 –