不开辟临时空间,实现以单词为单位反转字符串

2024-03-11 21:48

本文主要是介绍不开辟临时空间,实现以单词为单位反转字符串,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

摘自http://blog.chinaunix.net/uid-21228455-id-2406482.html

「原题
Write a function that reverse string word by word. 
For instance:
"The houst is blue" --> "blue is house the"
"Zed is dead"       --> "dead is Zed"
"All-in-one"        --> "All-in-one"
「两个方法
1. 先翻转整个字符串;再翻转每一个单词。
2. 先翻转每一个单词;再翻转整个字符串。
其实一样,只是先后顺序不同,严格来说,不能算两种方法。

「具体实现windows下(vc6.0, C语言)

/* 
我的假设
1. 单词严格以空格进行划分,最后一个单词以'\0'进行划分;
2. 删除单词间重复的空格,只保留一个;
3. 删除字符串末尾的空格;
4. 对于只有一个单词的字符串,不进行任何翻转动作(flag表示)。 
*/


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

/* memcpy函数的实现*/
void myMemcpy(void *dest, const void *src, size_t count)
{
    char *pDest = (char *)dest;
    char *pSrc = (char *)src;

    /* 目的地址和源地址重叠,从源地址的末尾方向开始拷贝 */
    if(pDest > pSrc && pDest < pSrc+count){
        for(pDest += (count-1), pSrc += (count-1); count != 0; count--){
            *pDest--= *pSrc--;
        }
    }else{
        /* 目的地址和源地址不重叠,从源地址的开始方向拷贝 */
        while(count--){
            *pDest++ = *pSrc++;
        }
    }

};

/* 不用临时变量,翻转字符串a[begin...end] */
void stringReverse(char a[], int begin, int end)
{
    for(; begin < end; begin++, end--){
        a[begin] ^= a[end];
        a[end] ^= a[begin];
        a[begin] ^= a[end];
    }
}

/* 以单词为单位翻转字符串 */
void stringReverseOnWord(char a[])
{
    char *begin = a;
    char *end = a;
    int len = strlen(a);
    int flag = 0;

    /* 对于空字符串以及只有一个字符的字符串不做任何处理 */
    if(*== '\0' || *(a+1) == '\0') {
        return;
    }

    /* 删除单词间重复的空格,只保留一个 */
    for(; *begin != '\0'; begin++){
        if(*begin == ' '){
            flag = 1;
            end = begin+1;
            while(*end == ' '){
                end++;
            }
            myMemcpy(begin+1, end, len-(end-1-a)); /* 完全可以用库函数代替,此处只是复习下memcpy的实现 */
        }
    }

 

 /* 删除重复空格时的情况

a             begin       end-1 end                 a+len

 c1

 ...

 cx

 空格

 ...

空格

 Cy

 ...

 cn-1

cn 

‘\0’ 

*/  

 

   /* end指向字符串结尾处'\0',在处理字符串前,还要将end指向最后一个非'\0'处 */
    end = begin;
    --end;
    
    /* 删除字符串末尾的空格 */
    while(*end == ' '){
        *end = '\0';
        end--;
    }

    /* 字符串不止一个单词,需要翻转 */
    if(flag == 1){
        stringReverse(a, 0, end-a);
        /* 删除字符串末尾的空格 */
        while(*end == ' '){
            *end = '\0';
            end--;
        }
        for(begin = end =a; *end != '\0'; end++){
            if(*end == ' '){ /* begin指向单词的第一个字符,(end-1)指向该单词的末尾 */
                stringReverse(begin, 0, end-1-begin);
                begin = end+1;
            }
        }

 

/*单词翻转时,begin和end指针的指向示意图

          begin    end-1 end               

 ...

空格

 c1

 ...

cx         

 空格

 Cy

 ...

 cn-1

cn 

‘\0’ 

*/

 


        /* 最后一个单词的处理 */
        if(*end == '\0' && end-begin > 1){
            stringReverse(begin, 0, end-begin-1);
        }
    }

}

int main()
{
    char a[] = "All-in-one";
    char b[] = " hello             I            will be with you";

    printf("%s\n", a);
    stringReverseOnWord(a);
    printf("%s\n", a);

    printf("%s\n", b);
    stringReverseOnWord(b);
    printf("%s\n", b);

    return 0;
}

这篇关于不开辟临时空间,实现以单词为单位反转字符串的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/799186

相关文章

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

SpringBoot基于注解实现数据库字段回填的完整方案

《SpringBoot基于注解实现数据库字段回填的完整方案》这篇文章主要为大家详细介绍了SpringBoot如何基于注解实现数据库字段回填的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解... 目录数据库表pom.XMLRelationFieldRelationFieldMapping基础的一些代

Java HashMap的底层实现原理深度解析

《JavaHashMap的底层实现原理深度解析》HashMap基于数组+链表+红黑树结构,通过哈希算法和扩容机制优化性能,负载因子与树化阈值平衡效率,是Java开发必备的高效数据结构,本文给大家介绍... 目录一、概述:HashMap的宏观结构二、核心数据结构解析1. 数组(桶数组)2. 链表节点(Node

Java AOP面向切面编程的概念和实现方式

《JavaAOP面向切面编程的概念和实现方式》AOP是面向切面编程,通过动态代理将横切关注点(如日志、事务)与核心业务逻辑分离,提升代码复用性和可维护性,本文给大家介绍JavaAOP面向切面编程的概... 目录一、AOP 是什么?二、AOP 的核心概念与实现方式核心概念实现方式三、Spring AOP 的关

Python实现字典转字符串的五种方法

《Python实现字典转字符串的五种方法》本文介绍了在Python中如何将字典数据结构转换为字符串格式的多种方法,首先可以通过内置的str()函数进行简单转换;其次利用ison.dumps()函数能够... 目录1、使用json模块的dumps方法:2、使用str方法:3、使用循环和字符串拼接:4、使用字符

Linux下利用select实现串口数据读取过程

《Linux下利用select实现串口数据读取过程》文章介绍Linux中使用select、poll或epoll实现串口数据读取,通过I/O多路复用机制在数据到达时触发读取,避免持续轮询,示例代码展示设... 目录示例代码(使用select实现)代码解释总结在 linux 系统里,我们可以借助 select、

Linux挂载linux/Windows共享目录实现方式

《Linux挂载linux/Windows共享目录实现方式》:本文主要介绍Linux挂载linux/Windows共享目录实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录文件共享协议linux环境作为服务端(NFS)在服务器端安装 NFS创建要共享的目录修改 NFS 配

通过React实现页面的无限滚动效果

《通过React实现页面的无限滚动效果》今天我们来聊聊无限滚动这个现代Web开发中不可或缺的技术,无论你是刷微博、逛知乎还是看脚本,无限滚动都已经渗透到我们日常的浏览体验中,那么,如何优雅地实现它呢?... 目录1. 早期的解决方案2. 交叉观察者:IntersectionObserver2.1 Inter

Spring Gateway动态路由实现方案

《SpringGateway动态路由实现方案》本文主要介绍了SpringGateway动态路由实现方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随... 目录前沿何为路由RouteDefinitionRouteLocator工作流程动态路由实现尾巴前沿S