Как вы перевернуть строку на месте в C или C ++? - PullRequest
165 голосов
/ 13 октября 2008

Как перевернуть строку в C или C ++, не требуя отдельного буфера для хранения обратной строки?

Ответы [ 29 ]

451 голосов
/ 13 октября 2008
#include <algorithm>
std::reverse(str.begin(), str.end());

Это самый простой способ в C ++.

160 голосов
/ 14 октября 2008

Читайте Кернигана и Ричи

#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;
    }
}
121 голосов
/ 13 октября 2008

зло C:

#include <stdio.h>

void strrev(char *p)
{
  char *q = p;
  while(q && *q) ++q;
  for(--q; p < q; ++p, --q)
    *p = *p ^ *q,
    *q = *p ^ *q,
    *p = *p ^ *q;
}

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

(Это XOR-swap вещь. Обратите внимание, что вы должны избегать обмена с самим собой, потому что ^ a == 0.)


Хорошо, хорошо, давайте исправим символы UTF-8 ...

#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/
  • Кроме того, UTF-8 более 0x10000 не проверен (поскольку у меня, кажется, нет ни одного шрифта для этого, ни терпения, чтобы использовать гекседитор)

Примеры: * 1 021 *

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

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

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

./strrev verrts/.
58 голосов
/ 07 февраля 2014

Перевернуть строку на месте (визуализация):

Reverse a string in place

40 голосов
/ 13 октября 2008

Не злой C, если принять общий случай, когда строка является нулевым символом char array:

#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--;
  }
}
34 голосов
/ 13 октября 2008

Вы используете std::reverse алгоритм из стандартной библиотеки C ++.

25 голосов
/ 03 июля 2011

Прошло много времени, и я не помню, какая книга научила меня этому алгоритму, но я подумал, что он довольно гениален и прост для понимания:

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);
22 голосов
/ 02 августа 2013

Используйте метод std :: reverse из STL :

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

Вам нужно будет включить библиотеку «алгоритм», #include<algorithm>.

20 голосов
/ 13 октября 2008

Обратите внимание, что прелесть std :: reverse заключается в том, что он работает со char * строками и std::wstring с так же, как и std::string с

void strrev(char *str)
{
    if (str == NULL)
        return;
    std::reverse(str, str + strlen(str));
}
11 голосов
/ 13 октября 2008

Если вы ищете реверсирование буферов с терминацией NULL, большинство решений, опубликованных здесь, в порядке. Но, как уже заметил Тим Фарли, эти алгоритмы будут работать только в том случае, если допустимо предположить, что строка является семантически массивом байтов (то есть однобайтовых строк), что, на мой взгляд, является неверным предположением.

Возьмем, к примеру, строку «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».

...