如何将一个句子中的单词倒置

目录

题目 

思路

代码实现

首先是连续输入含空格的字符串

接下来是对字符串逆序的实现

接下来是对单个单词的逆序        

下面是完整代码


 

题目 

思路

首先分析:题目要我们倒置单词,但是仍能保留原来单词的样子。而我们熟悉的是对字符串进行逆序,但这样子单词就不能保持原来的样子.

先不妨假设对整个句子进行逆序,原句变成 .gnijieb ekil I 

这时只需要再把其中的单词进行逆序 就可以得到  beijing. like I

而我们熟悉的对字符串逆序的实现方法,能不能对逐个单词使用呢?

答案是可以的,我们将逆序字符串的功能编写成一个函数,传参使用要逆序的字符串的首字符的地址和末尾字符的地址,当逆序不同的单词时,实际上只要传不同的首元素字符地址和尾元素字符地址就可以了。

本题中还有个难点,就是连续输入字符。

且这个连续输入的字符串中包含有空格,因此我们常用的scanf函数就不能用了,而要用gets函数。下面我们会详细拆解代码编写的过程。

代码实现

首先是连续输入含空格的字符串

先展示下错误输入,你看scanf函数读到空格时就不再读下去了。

 这是因为scanf函数规定了%s 的输入格式是在读取到第一个空格时就停止读取的。

我们在cplusplus.com网站上搜scanf函数的相关信息

scanf - C++ Reference (cplusplus.com)

 可以看到在s这个输入字符串格式中的描述就是这样的。

(翻译)任意数量的非空格字符,在找到的第一个空格字符处停止。终止空字符会自动添加到存储序列的末尾。

而这个终止空字符其实就是我们熟悉的 \0 了

我们再换成gets函数,就可以实现含空格的字符串输入了。

这是gets函数的描述。

gets输入函数是在敲完回车的时候就结束读取的,我们可以看到最后一段的描述,说gets不同于fgets函数,不仅仅是因为gets从stdin(就是键盘输入),而且它不会在最终的字符串中包含结束一行的字符,也就是gets读取到的字符串中是不含‘\n’的

而fgets函数也是可以实现含空格的字符串输入的函数,但是它会将'\n'也读取进来 

fgets(要存入数据的地址,输入的最大数量,从哪里读取数据);

而我们要进行逆序,在传逆序起始参数和终止参数的时候,如果要用fgets函数,就要注意末尾是到\n就终止,而不是到\0

 

接下来是对字符串逆序的实现

void reverse(char* left, char* right)
{
	char tmp = 0;
	while (left < right)
	{
		tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}

}

接下来是对单个单词的逆序        

int main()
{
	char arr[101] = { 0 };
	
	gets(arr);
	int len = strlen(arr);
	char* start = arr;
	char* end = arr + len - 1; //刚好指向最后一个元素的地址
	//整个句子的逆序
	reverse(start , end);
	end = arr; 
	//整个逆序单词的过程
	while (*end != '\0')
	{
		
		while (*end != ' ' && *end != '\0')
//找到一个单词的末尾的元素的地址 ,当退出循环的时候。end是末尾元素地址的下一位
		{
			end++;
		}
		reverse(start, end-1);  //注意end存的值的含义
		start = end + 1;
		end++;// end再次符合进入内层while循环的条件。
	}	
	printf("%s", arr);
	return 0;
}

通过while循环,遍历找到要逆序的字母的末尾元素地址
因为空格是不用逆序的,且不能通过strlen来计算需要逆序的字符串长度来得出末尾元素的地址,strlen 是遇\0停止的 而空格可不是\0
因为整个句子逆序完后,只有句子(整个字符串)结尾是有\0的,利用这点设计外层while循环。而内层找到每个要逆序的单词的末尾元素地址的循环也用while实现,只是判断条件要多设置一个判断是否为空格,为空格时,end++。即指向需要逆序的字符串的末尾元素的指针向后偏移一位,一直循环直到遇到空格或者\0。

完成一个单词的逆序后就是对start和end的调整,让start指向下一个单词的首元素地址,而end++,满足进入继续向后寻找空格的循环的条件。

其实这里外层循环的判断条件也可以直接设置成*end的。因为当*end = '\0'的时候,其实就是等于0.因为'\0'的ASCii码表对应的值就是数字0.所以当end指针偏移到最后,指向\0的时候,*end就是0,为假,退出while循环。

但是要注意,如果这么设置外层循环的判断条件,那么循环里面最后一行代码的end++就要加个if条件  if(end != '\0')

下面是完整代码


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

void reverse(char* left, char* right)
{
	char tmp = 0;
	while (left < right)
	{
		tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}

}

int main()
{
	char arr[101] = { 0 };
	
	gets(arr);
	int len = strlen(arr);
	char* start = arr;
	char* end = arr + len - 1; 
	reverse(start , end);

	end = arr; 
	while (*end != '\0')
	{
		
		while (*end != ' ' && *end != '\0')
		{
			end++;
		}
		reverse(start, end-1);  
		start = end + 1;
		end++;
	}	
	printf("%s", arr);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值