[英]Reverse words of string by recursion
我正在嘗試編寫一個 C function ,它接受一個字符串,並返回一個帶有反轉單詞的新字符串。 例如,輸入“How are you”應該返回“you are How”。 以下是我的試用:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *reverseWords(char *str, char *ac)
{
if (!ac)
{
ac = malloc(strlen(str) + 1);
ac[0] = '\0';
}
char *word = strtok(str, " ");
if (!word)
{
return ac;
}
reverseWords(NULL, ac);
strcat(ac, word);
//strcat(ac, " ");
}
int main()
{
char s[] = "How are you";
char *reversed = reverseWords(s, NULL);
printf("%s\n", reversed);
}
前面的代碼打印:“youareHow”,所以看起來這個想法是正確的,但只是缺少空格。 如果我試圖取消注釋 function 的最后一行,我沒有得到任何 output。 那么發生了什么? 我不明白為什么它不起作用。
您忽略了reverseWords
的返回值。 我認為這沒關系,因為您參考了ac
在reverseWords
function 的末尾,您沒有返回包含連接字符串的ac
。
現在你必須取消注釋strcat(ac, " ");
這樣空間將被添加到返回值。
現在返回值將包含帶有空格的反轉字符串。
您忘記釋放分配的字符串。
當您遞歸調用reverseWords
時,您會忽略返回碼,但這沒有問題,因為更高級別的調用已經引用了ac
。
但是最高級別的調用會將 function reverseWords
留在您忘記返回值的末尾。
當您的程序似乎通過打印“youareHow”部分工作時,您實際上觀察到了未定義的行為,因為main
function 顯然找到了它期望獲得返回值的預期字符串的地址。 由於 function 不返回值,這是 memory 或先前執行代碼的寄存器中剩余的東西。
像這樣更改您的代碼:
char *word = strtok(str, " ");
if (!word)
{
return ac;
}
reverseWords(NULL, ac);
strcat(ac, word);
strcat(ac, " ");
return ac;
}
請注意,您的代碼會在每個單詞后附加一個空格。 如果將 output 更改為
printf("<%s>\n", reversed);
要解決此問題,您可以更換
strcat(ac, word);
strcat(ac, " ");
和
if(ac[0] != '\0')
{
strcat(ac, " ");
}
strcat(ac, word);
如果ac
中的現有字符串不為空,這將在每個單詞之前插入一個空格。
我添加這個只是因為遲早我在 ideone.com 上支持的替代方法鏈接會腐爛,當它腐爛時,人們可能會想知道我在一般評論中談論的是什么。
此任務可以就地完成,無需動態分配或使用strtok
。 該方法使用稱為反向分區的技術,並通過執行以下操作來完成:
而已。 現在用數據查看它:
step 1,2. reverse the target sequence
"abc 123 xyz" ==> "cba 123 xyz"
^^^ ^^^
step 3. Reverse the entire sequence
"cba 123 xyz" ==> "zyx 321 abc"
step 3 Reverse the non-target sequence, not including the trailing space
"zyx 321 abc" => "123 xyz abc"
^^^^^^^ ^^^^^^^
對非目標段重復此操作(遞歸或迭代,沒有區別),調整結束標記以執行此操作。 第二次遍歷看起來像這樣,注意示例上方的結束標記*
的 position:
* *
"123 xyz abc" => "321 xyz abc"
^^^ ^^^
* *
"321 xyz abc" => "zyx 123 abc"
^^^^^^^ ^^^^^^^
* *
"zyx 123 abc" => "xyz 123 abc"
^^^ ^^^
完成后,再次遞歸。 現在介紹看起來像這樣:
*
"xyz 123 abc"
但請注意,字符串的開頭和結束標記之間沒有空格,所以我們完成了(如果你錯過了,我們已經完成了)。
編碼
執行此操作的實際代碼很簡單,只有指針數學需要幾眼才能完全理解。 這里是:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void reverse_letters(char *beg, char *end)
{
while (beg < --end)
{
char tmp = *beg;
*beg++ = *end;
*end = tmp;
}
}
char *reverse_words(char *beg, char *end)
{
// find whitespace. if none then we're done.
char *p = beg;
for (; p != end && !isspace((unsigned char)*p); ++p);
if (p != end)
{
reverse_letters(beg, p);
reverse_letters(beg, end);
reverse_letters(beg, beg + (end - p - 1));
reverse_words(beg, beg + (end - p - 1));
}
return beg;
}
int main()
{
char words[] = "abc 123 xyz";
reverse_words(words, words + strlen(words));
puts(words);
return 0;
}
Output
xyz 123 abc
顯然,這是一個可以得到的尾遞歸,因此適應迭代解決方案將是微不足道的,我將其作為練習留給讀者。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.