`
talentluke
  • 浏览: 604825 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

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

 
阅读更多

摘自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;
}

分享到:
评论

相关推荐

    华为机试题:压缩字符串

    通过键盘输入一串小写字母(a~z)组成的字符串,将字符串中连续出席的重复字母进行压缩,并输出压缩后的字符串。 压缩字段的格式为"字符重复的次数+字符... pOutputStr:输出字符串,空间已经开辟好,与输入字符串等长。

    使用SDS代码结构实现Redis字符串的编写.docx

    当需要增加字符串长度时,Redis会自动扩展其底层的缓存空间,并预留一定的额外空间,以备后续可能的增长需求。这种机制可以显著减少内存分配的频率,从而提高系统的整体性能。 例如,假设初始字符串`s1`仅有5个空闲...

    ReverseChar

    题目所提到的"ReverseChar"是一个编程挑战,旨在实现字符串反转的功能,同时强调在执行过程中不新开任何临时保存的字符串,以确保简洁且高效的解决方案。 传统的字符串反转方法通常会创建一个新的字符串来存储反转...

    C#字符串处理的相关操作

    当给一个字符串重新赋值之后,旧值并没有销毁,而是重新开辟了一块空间,存储新值。这也意味着,字符串的值一旦确定,就不能再修改它的内容。 访问字符串中的元素 字符串可以看成char类型的只读数组,所以可以访问...

    C语言的字符串及基本运算.pdf

    此时,尽管没有定义字符数组,C语言为字符串常量开辟了内存空间来存放字符串。 二、字符串的基本运算 C语言提供的标准库函数可以对字符串进行基本运算。这些运算包括输出、输入、长度计算、复制、连接和比较等。...

    探究C语言中的字符串.pdf

    字符指针是指向字符串的指针,占用的是内存中常量区的连续不间断的内存空间,在进行操作的时候就给出的是存放字符串的存储空间的首地址。要存储多个字符串数据就要使用字符指针数组 char*fr[4],一个一维 char* 数组...

    如何在c++中实现字符串分割函数split详解

    4. 数组生成:最后,我们需要根据统计的数量动态开辟一个字符串数组空间,并将队列中的数据转入数组中,最后返回处理完毕后的字符串数组的首地址。 完整代码如下所示: ```cpp #include #include #include #...

    STM32串口实验+自定义协议接收16进制数据+发送1个(2个)字符+发送字符串函数.zip

    这通常涉及开辟内存空间,使用数组或者结构体来保存数据。同时,还需要处理溢出和边界条件。 5. **十六进制转十进制**:从两个连续的十六进制数字中提取数据,并转换成十进制。这需要了解十六进制与十进制之间的...

    动态创建链表,在需要时开辟空间。

    这种链表在初始时不一定分配足够的空间, 但是在后续插入的时候需要动态申请存储空间,并且存储空间不一定连续, 在进行插入和删除时则不需要移动元素, 修改指针域即可...即在需要时才开辟结点的存储空间,实现动态链接。

    c语言中字符串的讲解[文].pdf

    字符指针可以指向字符串常量,但不会开辟新的内存空间。如果需要修改字符串,必须使用字符数组。 字符串的输入和输出主要通过`scanf`和`printf`,以及`gets`和`puts`这两个函数进行。 - `printf`函数使用`%s`格式化...

    在电脑里开辟一个保密,安全的空间

    这个特别小的文件可以在您的硬盘里临时开辟一个盘符出来,把你的隐私,你的电影,你的日记等等放进去吧.这个bat文件放在一个隐秘的地方.即使执行电脑的全盘搜索页搜不出来的!只要硬盘不出问题,即使从做系统,自己私密...

    实现单链表就地逆置且不分配新的空间

    在"就地逆置"的情况下,我们要求在不额外分配内存空间的情况下完成链表的逆置,即只使用原链表的节点空间进行操作。 单链表就地逆置的算法通常涉及三个指针:前驱指针(prev)、当前指针(curr)和临时指针(temp)...

    c++设计实现一个&quot;字符串类&quot;,要求系统设计具有一定弹性和可扩展性,使得后续维护和扩展功能更容易,增加或修改系统功能变得更简单。

    本次实验的任务为设计实现一个"字符串类",要求系统设计具有一定弹性和可扩展性,使得后续维护和扩展功能更容易,增加或修改系统功能变得更简单。基本要求和功能∶ 1、字符串类中存储字符串的成员变量必须定义为私有...

    开辟空间存放结构体变量.zip_开辟空间存放结构体变量

    这里的`Student`就是我们定义的一个结构体类型,包含三个成员:姓名(name)、年龄(age)和分数(score),它们分别属于字符串、整型和浮点型。 然后,为了在程序中使用这个结构体,我们需要创建结构体的实例,即...

    C语言模拟实现Linux文件系统

    1、在内存中开辟一块空间来模拟文件系统的运行,不读写硬盘。 2、面向单用户、单任务,不考虑并发,不考虑文件属主、组等概念。 3、程序开始后,初始化并接收用户输入。若输入”enter”,则重新建立文件系统, 读取...

    指针与字符串的有关理解

    而字符指针则可以动态地指向任何字符串,但需要先开辟存储空间,例如`char *cp; cp = "I love China!";`。 函数指针是另一个重要的概念,它允许我们将函数作为其他函数的参数或者返回值。函数指针的定义形式是`数据...

    数据结构-关于串的索引存储结构演示

    在**建立串的索引存储结构**的过程中,首先需要为存储字符串的值开辟一块连续的内存空间。这个空间会随着程序的运行动态分配和释放,以适应不同长度的字符串。接着,创建一个索引表,每个索引表项包含三个部分:字符...

    实验5 简单文件系统的实现

    文件目录结构设计为多级目录,每个目录项包含文件名、物理地址、文件长度等信息,可实现读写保护。实验要求实现以下命令: - `my_format`:对虚拟磁盘进行格式化,创建根目录和相关数据结构。 - `my_mkdir`:创建子...

    C语言字符串的模式匹配[收集].pdf

    空间复杂度为 O(1),不需要额外开辟空间存储。 KMP 算法 KMP 算法是一种线性时间复杂度的字符串匹配算法,它是对 BF 算法的改进。该算法的思想是利用已经得到的部分匹配信息来进行后面的匹配过程。其时间复杂度为 ...

    实现简单的文件系统

    1.在内存中开辟一个虚拟磁盘空间作为文件存储器,在其上实现一个简单的单用户文件系统。在退出这个简单的文件系统时,将该虚拟文件系统保存到磁盘上,以便下次再将它恢复到内存的虚拟磁盘空间中。 2.提供以下操作: ...

Global site tag (gtag.js) - Google Analytics