[刷题]倒置字符串单词

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第13天,点击查看活动详情

前言

       本文是关于刷题——倒置字符串单词的C语言实现。

       新手一个,水平比较低,还请包涵。

题目描述

【倒置字符串】

将一句话的单词进行倒置,标点不倒置。比如 I like beijing. 经过函数后变为:beijing. like I

输入描述:每个测试输入包含1个测试用例: I like beijing. 输入用例长度不超过100

输出描述:依次输出倒置之后的字符串,以空格分割

示例: 输入
I like beijing.
输出
beijing. like I

注意

     要认真审题,这可不是逆序字符串的每个字符,而是以单词为单位(包括标点符号,不过该题标点符号只考虑句末的点号 . ),让单词的顺序逆序。

递归分割法

如何分割

      既然要以单词为单位逆序,那么我们就先考虑一下把单词分割出来,怎么分呢?

      想想看,输入的字符串中每个单词之间是不是都以空格' '为间隔,以此来区别不同的单词,我们可不可以利用这一点来分割单词呢?

      而我们又知道:C语言里用'\0'来标示字符串的结束,那我们可以不可以把输入的字符串中的空格给换成'\0' 呢?这样一来原字符串就被分割成了若干个小的字符串,每一个小的字符串就是一个单词(包括标点符号),当我们要读取单个单词的时候只要知到单词头部的地址就可以了呗。

      我们用一个指针来标识单词的头部,让指针不断向后偏移,直到遇上空格或'\0'才停下,要是遇上空格的话,就把空格给换成'\0',然后从下一个字符处继续偏移重复上述过程。

图解

对应代码

void ReverseStr(char* str)
{
    //遇到空格说明到达单词末尾了
    //而遇到'\0'说明到达原字符串末尾了
    while((*str != ' ') && (*str != '\0'))
    {
        str++;
    }
    //单词末尾处,分割单词
    if(*str == ' ')
    {
        //把空格换成'\0'
        *str = '\0';
        //把指针向后偏移一个单位后递归
        ReverseStr(str + 1);
    }

}

如何逆序打印

      逆序什么的用递归省事多了,前面不是一直让指针向后偏移再递归嘛,正好偏移到原字符串末尾处时停下来,此时*str值为'\0',不符和if(*str == ' ')条件,也就不再递归下去了,那就开始打印。

      你可能会疑惑:你这样都让指针偏移到字符串末尾了还咋一个一个打印单词啊?

      别着急,我们只需要在每次进入函数时拷贝一份指针的值不就行了吗。

      况且每次分割完一个单词后才递归再次进入函数。

      不递归后开始打印字符串,因为是向后偏移递归,所以最先打印的就是最后的单词。

图解

对应代码

void ReverseStr(char* str)
{
    char* str_cy = str;
    while((*str != ' ') && (*str != '\0'))
    {
        str++;
    }
    if(*str == ' ')
    {
        *str = '\0';
        ReverseStr(str + 1);
    }

    printf("%s ", str_cy);
}

完整代码

#include<stdio.h>

void ReverseStr(char* str)
{
    char* str_cy = str;
    while((*str != ' ') && (*str != '\0'))
    {
        str++;
    }
    if(*str == ' ')
    {
        *str = '\0';
        ReverseStr(str + 1);
    }

    printf("%s ", str_cy);
}

int main()
{
    char str[101] = {0};
    gets(str);
    ReverseStr(str);

    return 0;
}

双重翻转法

思路

      先将整个字符串翻转逆序,再一个一个单词翻转逆序。

实现代码

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

int main()
{
	char str[1001] = {0};
	gets(str);

	char* left = str;
	int len = strlen(str);
	char* right = str + len - 1;
	ReverseStr(left, right);//整个字符串逆序翻转

	char* start = str;
	char* end = start;

	while (*start)//双指针偏移定位单词头尾位置以区分单词并逆序翻转
	{
		//用end找到单词末尾处(end-1)
		while (*end != ' ' && *end != '\0')
		{
			end++;
		}
		//逆序翻转一下单个单词
		ReverseStr(start, end - 1);
		//空格说明不是最后一个单词
		if (*end == ' ')
			end++;
		start = end;
		
	}
	printf("%s", str);

	return 0;
}