我添加这个内容是因为迟早我在ideone.com上支持的替代方法链接将会失效,当它失效时,人们可能会想知道我在一般评论中在说什么。
可以在不使用动态分配或使用strtok的情况下完成此任务。该方法使用一种称为“反转分区”的技术,通过执行以下操作来完成:
1. 从字符串开始到结束标记(最初作为终止符提供,但每次递归时都会减少)中找到第一个空格。如果在该段中未找到任何空格,则完成操作。
2. 反转从字符串开头到(1)中发现的分隔空格之前的片段。
3. 反转整个序列从开头到结束标记。
4. 反转从字符串开头到移动片段之前的空格之前的位置的片段。
5. 使用不包括刚刚移动的数据及其前导空格的段进行递归。
就是这样。现在看看它与数据一起使用:
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"
^^^^^^^ ^^^^^^^
对于非目标片段,重复执行此操作(递归或迭代均可),调整结束标记。第二次遍历应如下所示,注意结束标记*
位于示例上方:
* *
"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)
{
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;
}
输出
xyz 123 abc
显然,这是尾递归的极致,因此将其改为迭代解决方案将变得非常简单,这部分留给读者自己练习。
strtok
不为空时它会返回什么?嗯... - WhozCraigstrcat(ac, word);
之后添加strcat(ac, " ");
...此外最好使用return ac
终止函数(需要验证)。 - Sir Jo Black