如何在C或C ++中反转字符串?


Answers:


123

标准算法是使用指向起点/终点的指针,并将它们向内移动,直到它们在中间相遇或交叉。随手交换。


反向ASCII字符串,即以0结尾的数组,其中每个字符都适合1 char。(或其他非多字节字符集)。

void strrev(char *head)
{
  if (!head) return;
  char *tail = head;
  while(*tail) ++tail;    // find the 0 terminator, like head+strlen
  --tail;               // tail points to the last real char
                        // head still points to the first
  for( ; head < tail; ++head, --tail) {
      // walk pointers inwards until they meet or cross in the middle
      char h = *head, t = *tail;
      *head = t;           // swapping as we go
      *tail = h;
  }
}

// test program that reverses its args
#include <stdio.h>

int main(int argc, char **argv)
{
  do {
    printf("%s ",  argv[argc-1]);
    strrev(argv[argc-1]);
    printf("%s\n", argv[argc-1]);
  } while(--argc);

  return 0;
}

相同的算法适用于已知长度的整数数组,仅使用tail = start + length - 1而不是查找结束循环即可。

(编者注:此答案最初也用于此简单版本的XOR-swap。已修复,以供将来阅读此热门问题的读者使用。 强烈建议不要使用XOR-swap;它很难阅读,使您的代码编译效率降低。您可以在Godbolt编译器资源管理器上看到使用gcc -O3为x86-64编译xor-swap时,asm循环体要复杂得多。)


好的,让我们修复UTF-8字符...

(这是XOR交换的东西。请注意,您必须避免与self交换,因为如果*p*q处于同一位置,则将a ^ a == 0对其进行清零。XOR交换取决于有两个不同的位置,将它们各自用作临时存储。)

编者注:您可以使用tmp变量用安全的内联函数替换SWP。

#include <bits/types.h>
#include <stdio.h>

#define SWP(x,y) (x^=y, y^=x, x^=y)

void strrev(char *p)
{
  char *q = p;
  while(q && *q) ++q; /* find eos */
  for(--q; p < q; ++p, --q) SWP(*p, *q);
}

void strrev_utf8(char *p)
{
  char *q = p;
  strrev(p); /* call base case */

  /* Ok, now fix bass-ackwards UTF chars. */
  while(q && *q) ++q; /* find eos */
  while(p < --q)
    switch( (*q & 0xF0) >> 4 ) {
    case 0xF: /* U+010000-U+10FFFF: four bytes. */
      SWP(*(q-0), *(q-3));
      SWP(*(q-1), *(q-2));
      q -= 3;
      break;
    case 0xE: /* U+000800-U+00FFFF: three bytes. */
      SWP(*(q-0), *(q-2));
      q -= 2;
      break;
    case 0xC: /* fall-through */
    case 0xD: /* U+000080-U+0007FF: two bytes. */
      SWP(*(q-0), *(q-1));
      q--;
      break;
    }
}

int main(int argc, char **argv)
{
  do {
    printf("%s ",  argv[argc-1]);
    strrev_utf8(argv[argc-1]);
    printf("%s\n", argv[argc-1]);
  } while(--argc);

  return 0;
}
  • 为什么,是的,如果输入很闷,这会很高兴地交换到该位置之外。
  • 破坏UNICODE时的有用链接:http : //www.macchiato.com/unicode/chart/
  • 另外,超过0x10000的UTF-8未经测试(因为我似乎没有任何字体,也没有耐心使用hexeditor)

例子:

$ ./strrev Räksmörgås ░▒▓○◔◑◕●

░▒▓○◔◑◕● ●◕◑◔○▓▒░

Räksmörgås sågrömskäR

./strrev verrts/.

162
在混淆的代码竞争之外没有充分的理由使用XOR交换。
克里斯·康威

28
您认为“就地”的意思是“没有额外的内存”,甚至临时的O(1)内存也没有?那么str和返回地址在堆栈上的空间又如何呢?
克里斯·康威,

55
@Bill,这不是“就地”的通用定义。就地算法可能会使用额外的内存。但是,此额外内存的数量不得取决于输入-即它必须是恒定的。因此,使用附加存储进行值交换是完全就位的。
康拉德·鲁道夫

19
在xor交换消失之前,不要更改此权限。
亚当·罗森菲尔德

34
XOR交换比通过现代乱序处理器上的寄存器进行交换要慢。
PatrickSchlüter

464
#include <algorithm>
std::reverse(str.begin(), str.end());

这是C ++中最简单的方法。


6
在C ++中,字符串由字符串类表示。他没有要求“字符星”或“字符括号”。保持优雅,C.
jokoon

10
@fredsbend,所选答案的“长得离谱”版本处理了这种简单答案无法解决的情况-UTF-8输入。它显示了充分说明问题的重要性。此外,问题是关于在C语言中也可以使用的代码。
Mark Ransom 2013年

5
如果您使用支持UTF-8的字符串类(或者可能是带有std :: basic_string的utf-8字符类),则此答案确实可以解决这种情况。此外,问题是“ C或C ++”,而不是“ C和C ++”。C ++仅是“ C或C ++”。
Taywee '16

161

阅读Kernighan和Ritchie

#include <string.h>

void reverse(char s[])
{
    int length = strlen(s) ;
    int c, i, j;

    for (i = 0, j = length - 1; i < j; i++, j--)
    {
        c = s[i];
        s[i] = s[j];
        s[j] = c;
    }
}

8
在我的iPhone上测试,这比使用原始指针地址慢了大约15%
jjxtra 2013年

3
变量“ c”不应该是char而不是int吗?
Lesswire 2013年

17
在此示例中要注意的重要一点是,字符串s必须以数组形式声明。换句话说,char s[] = "this is ok"不是char *s="cannot do this"因为后者导致无法修改的字符串常量
user1527227

3
向“教父”道歉....“离开枪支,带上K&R”。作为一个C偏执的人,我会使用指针,因为他们对这个问题更简单,更直接,但代码会少移植到C#,Java等

2
@Eric这不会在O(log(n))时间内运行。如果要引用代码执行的字符交换数量,则它以O(n)运行,对于n个字符串长度,则执行n个交换。如果您正在谈论执行的循环数量,那么它仍然是O(n)-尽管是O(n / 2),但是您使用Big O表示法删除了常数。
史蒂芬·福克斯

62

在原处反转字符串(可视化):

Reverse a string in place


凉!您是用什么来创建这个的?我认为,通过包含一个链接可以改善答案。
Pryftan

该算法的实现实际上就是这个答案
卡尔菲利普

您能对此做些解释吗,如果图像链接消失了,答案将不会是没有用的?
SS安妮

41

非邪恶的C,假设字符串是一个以null终止的char数组的常见情况:

#include <stddef.h>
#include <string.h>

/* PRE: str must be either NULL or a pointer to a 
 * (possibly empty) null-terminated string. */
void strrev(char *str) {
  char temp, *end_ptr;

  /* If str is NULL or empty, do nothing */
  if( str == NULL || !(*str) )
    return;

  end_ptr = str + strlen(str) - 1;

  /* Swap the chars */
  while( end_ptr > str ) {
    temp = *str;
    *str = *end_ptr;
    *end_ptr = temp;
    str++;
    end_ptr--;
  }
}

您不能使用end_ptr = str + strlen(str)之类的东西来代替使用while循环来查找结束指针;我知道这几乎可以做同样的事情,但是我发现更清楚。
彼得·库恩(PeterKühne)

很公平。我正在尝试(并且失败)避免@uvote答案中的偏离一处的错误。
克里斯·康威

除了可以改善潜在的性能外int temp,该解决方案看起来也是最好的。+1
chux-恢复莫妮卡2014年

@ chux-ReinstateMonica是的。真漂亮。就个人而言,我会从中删除()!(*str)
Pryftan

@PeterKühne是的或strchr()正在搜索'\0'。我都想到了。不需要循环。
Pryftan

35

您可以使用std::reverseC ++标准库中的算法。


14
标准模板库是一个标准前术语。C ++标准没有提及它,并且以前的STL组件在C ++标准库中。
Nemanja Trifunovic

16
对。我总是想知道为什么这么多人仍然称其为“ STL”,尽管它只是使事情变得混乱。如果有更多的人喜欢您,并且将其命名为“ C ++ Standard Library”或STL并说“ STANDard Library”
,那就更好了

27

已经有一段时间了,我不记得哪本书教了我这种算法,但是我认为它相当巧妙而且易于理解:

char input[] = "moc.wolfrevokcats";

int length = strlen(input);
int last_pos = length-1;
for(int i = 0; i < length/2; i++)
{
    char tmp = input[i];
    input[i] = input[last_pos - i];
    input[last_pos - i] = tmp;
}

printf("%s\n", input);

是一个有趣的变化。从技术上来说应该是size_t
Pryftan

24

使用STLstd :: reverse方法:

std::reverse(str.begin(), str.end());

您将必须包含“ algorithm”库#include<algorithm>


1
需要包括哪个库?
Don Cruickshank

的#include <算法>我忘了写,然后编辑的答案,但它不是保存,这就是为什么名失踪..
user2628229

尽管这也是我的答案,但很好奇,因为OP要求“没有缓冲区来保存反向字符串”(基本上是就地交换),那么如何证明这一点呢?有没有人解释说它内部使用std :: iter_swap <>从两个端点迭代到缓冲区的中点?另外,OP要求使用C和C ++,这仅适用于C ++(我们可以希望<string.h>具有strrev()方法吗?)
HidekiAI 2016年

21

请注意,std :: reverse的优点在于它可以与char *string和std::wstrings以及std::strings一起使用

void strrev(char *str)
{
    if (str == NULL)
        return;
    std::reverse(str, str + strlen(str));
}

1
一方面,我想呕吐是因为您使用了C ++,但另一方面,看到有人使用C ++而不是*按类型输入,而是按名称输入,则是一件美丽,美丽,绝对美丽的事情。精彩。我承认我是一个纯粹主义者,但是每当我看到类似的代码时我都会畏缩char* str;
Pryftan

11

如果您正在寻找反向NULL终止的缓冲区,这里发布的大多数解决方案都可以。但是,正如蒂姆·法利(Tim Farley)所指出的那样,这些算法只有在假设字符串在语义上是字节数组(即单字节字符串)的前提下才有效,我认为这是一个错误的假设。

以字符串“año”(西班牙语中的年份)为例。

Unicode代码点为0x61、0xf1、0x6f。

考虑一些最常用的编码:

Latin1 / iso-8859-1(单字节编码,1个字符为1个字节,反之亦然):

原版的:

0x61、0xf1、0x6f,0x00

逆转:

0x6f,0xf1、0x61、0x00

结果还可以

UTF-8:

原版的:

0x61、0xc3、0xb1、0x6f,0x00

逆转:

0x6f,0xb1、0xc3、0x61、0x00

结果是乱码和非法的UTF-8序列

UTF-16 Big Endian:

原版的:

0x00、0x61、0x00、0xf1、0x00、0x6f,0x00、0x00

第一个字节将被视为NUL终止符。不可逆转。

UTF-16 Little Endian:

原版的:

0x61、0x00、0xf1、0x00、0x6f,0x00、0x00、0x00

第二个字节将被视为NUL终止符。结果将是0x61、0x00,这是一个包含'a'字符的字符串。


只要您使用wstring,std :: reverse将适用于两字节的unicode类型。

我对C ++不太熟悉,但是我猜想任何处理字符串的标准库函数都可以处理不同的编码,所以我同意你的看法。所谓“这些算法”,是指此处发布的临时反向功能。
Juan Pablo Califano,

不幸的是,在标准C ++中没有“可处理字符串的可观函数”之类的东西。
2012年

@Eclipse如果它反转一个代理对,结果将不再正确。Unicode实际上不是固定宽度的字符集
phuclv 2014年

我对这个答案的满意之处在于它显示了字节的实际顺序(尽管字节序可能是某些东西-啊,我看您确实考虑了它)以及它是正确还是错误。但是我认为,如果您合并一些演示此问题的代码,答案将会得到改善。
Pryftan

11

在完整的利益,应该指出的是,也有在各种平台上,其中每个字符的字节数的字符串表示变化取决于字符。老派程序员会将其称为DBCS(双字节字符集)。现代程序员在UTF-8(以及UTF-16等)中更常见。还有其他这样的编码。

在任何这些可变宽度编码方案中,此处发布的简单算法(EvilNon-evil其他)都根本无法正常工作!实际上,在该编码方案中,它们甚至可能导致字符串变得难以辨认甚至是非法字符串。有关一些很好的示例,请参见Juan Pablo Califano的答案

只要您平台对标准C ++库的实现(特别是字符串迭代器)正确考虑了这种情况,std :: reverse()在这种情况下可能仍然可以工作。


6
std :: reverse没有考虑到这一点。它反转了value_type的值。在std :: string情况下,它反转char的。不是字符。
MSalters

可以说,我们守旧派的程序员了解DBCS,但也了解UTF-8:因为我们都知道程序员就像瘾君子一样,当他们说“再一行,我就退出!” 我敢肯定,有些程序员最终会退出,但是坦率地说,编程对我来说真的像上瘾了。我从不编程中退出。在这里添加一个好点。我不喜欢C ++(即使编写了很多代码,我都非常努力地喜欢它,但是至少从美学上来说,这对我来说仍然没有吸引力),所以我无法在此发表评论,但是无论如何您都说得很对。 +1。
Pryftan

5

另一种C ++方式(尽管我可能会自己使用std :: reverse():)来提高表现力和速度)

str = std::string(str.rbegin(), str.rend());

C方式(或多或少:)),请注意交换的XOR技巧,编译器有时无法对其进行优化。

在这种情况下,通常速度要慢得多。

char* reverse(char* s)
{
    char* beg = s, *end = s, tmp;
    while (*end) end++;
    while (end-- > beg)
    { 
        tmp  = *beg; 
        *beg++ = *end;  
        *end =  tmp;
    }
    return s;
} // fixed: check history for details, as those are interesting ones

strlen如果可能很长,我会用它来查找字符串的结尾。一个好的库实现将使用SIMD向量来搜索,每次迭代的速度快于1个字节。但是对于非常短的字符串,while (*++end);将在开始搜索库函数调用之前完成。
彼得·科德斯

@PeterCordes很好,同意,无论如何都应使用strlen以提高可读性。对于更长的字符串,无论如何,应始终将长度保持不变。通常在此免责声明中举例说明在SIMD上吃惊,这不是现实生活中的应用程序,或者至少是在5年前编写代码时。;)
pprzemek

1
如果希望此方法在真实的CPU上快速运行,则可以使用SIMD随机播放以16B块为单位执行相反操作。_mm_shuffle_epi8给定正确的随机播放控制向量,例如x86上的:P (PSHUFB)可以反转16B向量的顺序。经过一些精心的优化,它可能可以以接近memcpy的速度运行,尤其是对于AVX2。
彼得·科德斯

char* beg = s-1具有未定义的行为(至少如果s指向数组的第一个元素,这是最常见的情况)。while (*++end);如果s为空字符串,则具有未定义的行为。
melpomene '18 -10-17

@pprzemek好吧,s-1即使是s指向数组的第一个元素,您也要声明已定义行为的声明,因此应该由您来引用支持的标准。
melpomene

4
#include <cstdio>
#include <cstdlib>
#include <string>

void strrev(char *str)
{
        if( str == NULL )
                return;

        char *end_ptr = &str[strlen(str) - 1];
        char temp;
        while( end_ptr > str )
        {
                temp = *str;
                *str++ = *end_ptr;
                *end_ptr-- = temp;
        }
}

int main(int argc, char *argv[])
{
        char buffer[32];

        strcpy(buffer, "testing");
        strrev(buffer);
        printf("%s\n", buffer);

        strcpy(buffer, "a");
        strrev(buffer);
        printf("%s\n", buffer);

        strcpy(buffer, "abc");
        strrev(buffer);
        printf("%s\n", buffer);

        strcpy(buffer, "");
        strrev(buffer);
        printf("%s\n", buffer);

        strrev(NULL);

        return 0;
}

此代码产生以下输出:

gnitset
a
cba

2
@uvote,不要使用strcpy。曾经 如果必须使用strcpy之类的东西,请使用strncpy。strcpy很危险。顺便说一下,C和C ++是两种具有不同功能的独立语言。我认为您正在使用仅在C ++中可用的头文件,因此您真的需要C语言的答案吗?
Onorio Catenacci

6
如果程序员可以跟踪其数组的大小,则strcpy是绝对安全的,许多人认为strncpy不太安全,因为它不能保证结果字符串以null结尾。无论如何,这里uvote使用strcpy并没有错。
罗伯特·格兰伯

1
@Onorio Catenacci,如果您知道源字符串将适合目标缓冲区,则strcpy并不危险,如上述代码中给出的情况。另外,如果有剩余空间,则strncpy零填充最多为size参数中指定的字符数,这可能是不希望的。
克里斯·杨

3
任何人都不能正常使用的strcpy不应该被编程C.
罗伯特宝洁

2
@Robert Gamble,我同意。但是,由于我不知道有什么方法可以阻止人们使用C语言进行编程,无论他们的能力如何,所以我通常建议您反对这样做。
Onorio Catenacci


3

我喜欢Evgeny的K&R答案。但是,很高兴看到使用指针的版本。否则,它基本上是相同的:

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

char *reverse(char *str) {
    if( str == NULL || !(*str) ) return NULL;
    int i, j = strlen(str)-1;
    char *sallocd;
    sallocd = malloc(sizeof(char) * (j+1));
    for(i=0; j>=0; i++, j--) {
        *(sallocd+i) = *(str+j);
    }
    return sallocd;
}

int main(void) {
    char *s = "a man a plan a canal panama";
    char *sret = reverse(s);
    printf("%s\n", reverse(sret));
    free(sret);
    return 0;
}

3

递归函数,用于在适当的位置反转字符串(没有额外的缓冲区,malloc)。

简短,性感的代码。堆栈使用率不好。

#include <stdio.h>

/* Store the each value and move to next char going down
 * the stack. Assign value to start ptr and increment 
 * when coming back up the stack (return).
 * Neat code, horrible stack usage.
 *
 * val - value of current pointer.
 * s - start pointer
 * n - next char pointer in string.
 */
char *reverse_r(char val, char *s, char *n)
{
    if (*n)
        s = reverse_r(*n, s, n+1);
   *s = val;
   return s+1;
}

/*
 * expect the string to be passed as argv[1]
 */
int main(int argc, char *argv[])
{
    char *aString;

    if (argc < 2)
    {
        printf("Usage: RSIP <string>\n");
        return 0;
    }

    aString = argv[1];
    printf("String to reverse: %s\n", aString );

    reverse_r(*aString, aString, aString+1); 
    printf("Reversed String:   %s\n", aString );

    return 0;
}

1
这是一个非常有趣的解决方案,您应该添加一些跟踪,例如printf(“%* s> [%d] reverse_r('%c',%p = \”%s \“,%p = \”%s \“) \ n“,depth,”“,depth,val,s,(s?s:” null“),n,(n?n:” null“))); 开头和<末尾。
贝诺瓦

各推char到堆栈不能算作“到位”。特别是当您实际上每个字符按4 * 8B(在64位计算机上:3个args +一个返回地址)时,尤其如此。
彼得·科德斯

最初的问题是“如何在C或C ++中反转字符串而不需要单独的缓冲区来保存反转的字符串?” -无需交换“就地”。另外,此解决方案从一开始就提到了不良的堆栈使用情况。我是否因为其他人的阅读能力差而被否决?
西蒙·佩弗里特

1
我不会称其为“性感”,但我会说这是示范性和指导性的。如果正确使用递归,则可能非常有价值。但是应该指出的是-最后我知道-C本身甚至不需要堆栈;但是它确实递归。无论哪种方式,它都是递归的一个例子,如果使用得当,它将非常有用和有价值。我认为我从未见过它曾经用来反转字符串。
Pryftan


1

分享我的代码。作为C ++学习者,作为使用swap()的一种选择,我很谦虚地要求发表评论。

void reverse(char* str) {
    int length = strlen(str);
    char* str_head = str;
    char* str_tail = &str[length-1];
    while (str_head < str_tail) 
        swap(*str_head++, *str_tail--);
}


0

完后还有:

#include <stdio.h>
#include <strings.h>

int main(int argc, char **argv) {

  char *reverse = argv[argc-1];
  char *left = reverse;
  int length = strlen(reverse);
  char *right = reverse+length-1;
  char temp;

  while(right-left>=1){

    temp=*left;
    *left=*right;
    *right=temp;
    ++left;
    --right;

  }

  printf("%s\n", reverse);

}

这演示了指针算法,很像我的答案,但是将它与Swap结合使用。我相信这个答案实际上增加了很多。您应该能够理解这种类型的代码,然后再添加十亿个库作为依赖关系,以便获得一些简单的文本框(在我使用的现代应用程序中,我经常看到这种情况)
Stephen J

0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

unsigned char * utf8_reverse(const unsigned char *, int);
void assert_true(bool);

int main(void)
{
    unsigned char str[] = "mañana mañana";
    unsigned char *ret = utf8_reverse(str,  strlen((const char *) str) + 1);

    printf("%s\n", ret);
    assert_true(0 == strncmp((const char *) ret, "anãnam anañam", strlen("anãnam anañam") + 1));

    free(ret);

    return EXIT_SUCCESS;
}

unsigned char * utf8_reverse(const unsigned char *str, int size)
{
    unsigned char *ret = calloc(size, sizeof(unsigned char*));
    int ret_size = 0;
    int pos = size - 2;
    int char_size = 0;

    if (str ==  NULL) {
        fprintf(stderr, "failed to allocate memory.\n");
        exit(EXIT_FAILURE);
    }

    while (pos > -1) {

        if (str[pos] < 0x80) {
            char_size = 1;
        } else if (pos > 0 && str[pos - 1] > 0xC1 && str[pos - 1] < 0xE0) {
            char_size = 2;
        } else if (pos > 1 && str[pos - 2] > 0xDF && str[pos - 2] < 0xF0) {
            char_size = 3;
        } else if (pos > 2 && str[pos - 3] > 0xEF && str[pos - 3] < 0xF5) {
            char_size = 4;
        } else {
            char_size = 1;
        }

        pos -= char_size;
        memcpy(ret + ret_size, str + pos + 1, char_size);
        ret_size += char_size;
    }    

    ret[ret_size] = '\0';

    return ret;
}

void assert_true(bool boolean)
{
    puts(boolean == true ? "true" : "false");
}

0

使用C ++ lambda:

 auto reverse = [](std::string& s) -> std::string {
        size_t start = 0, end = s.length() -1;
        char temp;

        while (start < end) {
          temp = s[start];
          s[start++] = s[end];
          s[end--] = temp;
        } 

        return s;
   };

0

我的答案与大多数答案相似,但请在此处找到我的代码。

//Method signature to reverse string
string reverseString(string str);

int main(void){
    string str;
    getline(cin, str);
    str =  reverseString(str);
    cout << "The reveresed string is : " << str;
    return 0;
}

/// <summary>
///     Reverses the input string.
/// </summary>
/// <param name="str">
///    This is the input string which needs to be reversed.
/// </param>
/// <return datatype = string>
///     This method would return the reversed string
/// </return datatype>

string reverseString(string str){
    int length = str.size()-1;
    char temp;
    for( int i=0 ;i<(length/2);i++)
    {
        temp = str[i];
        str[i] = str[length-i];
        str[length-i] = temp;
    }
    return str;
}

0

我认为还有另一种方法可以反转字符串。从用户那里获取输入并反转。

void Rev() {
    char ch;
    cin.get(ch);
    if(ch != '\n') {
        Rev();
        cout.put(ch);
    }
}

是的,但这只会打印出相反的顺序,对吗?(我不使用C ++,所以.put()可能不执行我认为的操作)。
Pryftan

-1

如果您不需要存储它,可以减少花费的时间,如下所示:

void showReverse(char s[], int length)
{
    printf("Reversed String without storing is ");
    //could use another variable to test for length, keeping length whole.
    //assumes contiguous memory
    for (; length > 0; length--)
    {
        printf("%c", *(s+ length-1) );
    }
    printf("\n");
}

我似乎是唯一没有缓冲区或temp变量的答案。我使用字符串的长度,但是其他执行此操作的人为头添加了另一个(相对于尾部)。我假设标准反向函数通过交换或其他方式存储变量。因此,我的印象是,假设指针数学和UTF类型对齐,这可能是唯一真正回答问题的答案。可以取出添加的printf(),我只是为了使结果看起来更好。我写这个是为了提高速度。没有额外的分配或变量。可能是显示反向str()的最快算法
Stephen J,

-3

这是我在C语言中的观点。它是为练习而设计的,并且尽可能简洁!您可以通过命令行输入一个字符串,即./program_name“在此处输入字符串”

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

void reverse(int s,int e,int len,char t,char* arg) {
   for(;s<len/2;t=arg[s],arg[s++]=arg[e],arg[e--]=t);
}

int main(int argc,char* argv[]) {
  int s=0,len=strlen(argv[1]),e=len-1; char t,*arg=argv[1];
  reverse(s,e,len,t,arg);
  for(s=0,e=0;e<=len;arg[e]==' '||arg[e]=='\0'?reverse(s,e-1,e+s,t,arg),s=++e:e++);
  printf("%s\n",arg);
}

1
这是一个难以理解的烂摊子,但是您显然不打算使用最短的代码(代码golf),因为某些变量名不止一个字符。
彼得·科德斯

-4

但是我认为XOR交换算法是最好的...

char str[]= {"I am doing reverse string"};
char* pStr = str;

for(int i = 0; i != ((int)strlen(str)-1)/2; i++)
{
    char b = *(pStr+i);
    *(pStr+i) = *(pStr+strlen(str)-1-i);
    *(pStr+strlen(str)-1-i) = b;
}

strlen()在循环条件和循环主体中调用可能无法优化。
彼得·科德斯

-5

这是在C ++中反转字符串的最干净,最安全,最简单的方法(我认为):

#include <string>

void swap(std::string& str, int index1, int index2) {

    char temp = str[index1];
    str[index1] = str[index2];
    str[index2] = temp;

}

void reverse(std::string& str) {

    for (int i = 0; i < str.size() / 2; i++)
        swap(str, i, str.size() - i - 1);

}

一种替代方法是使用std::swap,但是我喜欢定义自己的函数-这是一个有趣的练习,您不需要include任何额外的操作。


-5
#include<stdio.h>
#include<conio.h>

int main()
{
    char *my_string = "THIS_IS_MY_STRING";
    char *rev_my_string = my_string;

    while (*++rev_my_string != '\0')
        ;

    while (rev_my_string-- != (my_string-1))
    {
        printf("%c", *rev_my_string);
    }

    getchar();
    return 0;
}

这是C语言中用于反转字符串的优化代码。只需使用简单的指针即可完成工作...


这一次打印字符串一个字符。它不会就地反转它。它还无故等待用户输入。
彼得·科德斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.