将字符数组:“student a am i”,改为:“i am a student”

问题:有一个字符数组的内容为:"student a am i",请你将数组的内容改为"i am a student".

           要求:不能使用库函数。只能开辟有限个空间(空间个数和字符串的长度无关)。 

思路分析:首先,大家会想到我把每个先将整个数组前后交换,这样的思考方式就会出现“i ma a tneduts”,这样的话就会出现单词的反转了,我们再让每个单词翻转过来就行了。
    这里的翻转在重复的使用,所以我们把翻转的步骤封装为一个函数,只要找到翻转的前面和后面,就可以完成翻转,所以需要两个字符指针:*left 和 *right
代码实现:

    (1)交换函数:

void reverse(char *left, char *right)
{
	assert(left);	//断言指针是否为空,如果是空指针就结束,不进行下面步骤
	assert(right);

	while (left < right)	//用于交换的主函数,如果传来要交换的头地址和尾地址,就可以完成交换
	{
		char tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}
        图解:

    (2)交换函数写完后我们就需要传址交换了,

        第一步:需完成整个字符串的交换,将字符串的第一个元素和最后一个字符(\0的前一个字符)地址传进去,然后实现交换;

        第二步:将每个单词交换,我们开始可能会想到我手动的将他们每个单词的地址传进去,不就实现了吗?但是电脑的出现不就是为了让人更加便利吗?所以我们通过思考会发现,这些单词的截止处不是‘ ’(空格)就是‘\0’,所以我们以这个为截止,开始将单词的起始位置记住,进行双层循环是不是就可以实现了呢?

代码如下:

void strReverse(char *str, int sz)	
{
	assert(str);
	reverse(str, str + sz - 1);    //用于逆置整个字符串
	while (*str != '\0')    //用于逆置每个单词
	{
		char *p = str;    //记住每一个单词的起始位置
		while ((*str != ' ') && (*str != '\0'))    //找寻每个单词的终止位置
		{
			str++;
		}
		reverse(p, str - 1);    //找到空格处,前一个就为单词的最后一个字母
		if (*str != '\0')
		{
			str++;
		}
	}
}

图解:



全部代码:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>


void reverse(char *start, char *end)	//用于逆序整个字符串
{
	assert(start);
	assert(end);
	while (start < end)
	{
		char* tmp = *start;
		*start = *end;
		*end = tmp;
		start++;
		end--;
	}
}

void strReverse(char *str, int sz)	//用于逆序一个单词
{
	assert(str);
	reverse(str, str + sz - 1);
	while (*str != '\0')
	{
		char *p = str;
		while ((*str != ' ') && (*str != '\0'))
		{
			str++;
		}
		reverse(p, str - 1);
		if (*str != '\0')
		{
			str++;
		}
	}
}

int main()
{
	//1、让整个语句逆序:i ma a tneduts
	//2、让每个单词逆序:i am a student
	char arr[] = "student a am i";
	int sz = strlen(arr);
	strReverse(arr, sz);
	printf("%s\n", arr);
	system("pause");
	return 0;
}



猜你喜欢

转载自blog.csdn.net/meng_lemon/article/details/80329875