Как Вы инвертируете строку на месте в C или C++?

В Java все находится в форме класса.

Если вы хотите использовать любой объект, тогда у вас есть две фазы:

  1. Объявить
  2. Инициализация

Пример:

  • Объявление: Object a;
  • Инициализация: a=new Object();

То же самое для концепции массива

  • Объявление: Item i[]=new Item[5];
  • Инициализация: i[0]=new Item();

Если вы не дают секцию инициализации, тогда возникает NullpointerException.

170
задан Coding Mash 24 November 2012 в 03:35
поделиться

10 ответов

Зло 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-подкачки. Всего хорошего, чтобы отметить, что необходимо избежать свопинг с сам, потому что a^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;
}
  • Да ведь да, если вход является borked, это бодро подкачает вне места.
  • Полезная ссылка при разрушении в UNICODE: http://www.macchiato.com/unicode/chart/
  • кроме того, UTF-8 по 0x10000 не тестируется (поскольку у меня, кажется, нет шрифта для него, ни терпения использовать hexeditor)

Примеры:

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

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

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

./strrev verrts/.
122
ответ дан Peter Cordes 23 November 2019 в 20:44
поделиться

В случае, если Вы используете Бойкий, это имеет две функции для этого, g_strreverse () и g_utf8_strreverse ()

3
ответ дан dmityugov 23 November 2019 в 20:44
поделиться
#include <algorithm>
std::reverse(str.begin(), str.end());

Это - самый простой путь в C++.

454
ответ дан Tom 23 November 2019 в 20:44
поделиться

Read 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;
    }
}
162
ответ дан Eric Leschinski 23 November 2019 в 20:44
поделиться

Незло C, принимая общий падеж, где строка является завершенным пустым указателем 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--;
  }
}
40
ответ дан Chris Conway 23 November 2019 в 20:44
поделиться

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

35
ответ дан Nemanja Trifunovic 23 November 2019 в 20:44
поделиться

Обратите внимание что красота станд.:: реверс - то, что это работает с char * строки и std::wstring с точно так же как std::string s

void strrev(char *str)
{
    if (str == NULL)
        return;
    std::reverse(str, str + strlen(str));
}
20
ответ дан Eclipse 23 November 2019 в 20:44
поделиться

При поиске инвертирования завершенных буферов ПУСТОГО УКАЗАТЕЛЯ большинство решений, отправленных здесь, в порядке. Но, как Tim Farley уже указал, эти алгоритмы будут работать, только если это допустимо, чтобы предположить, что строка является семантически массивом байтов (т.е. однобайтовые строки), который является неправильным предположением, я думаю.

Берут, например, строка "aГ±o" (год на испанском языке).

кодовые точки Unicode являются 0x61, 0xf1, 0x6f.

Рассматривают часть наиболее используемой кодировки:

Latin1 / iso-8859-1 (единственное кодирование байта, 1 символ составляет 1 байт и наоборот):

Исходный:

0x61, 0xf1, 0x6f, Реверс 0x00

:

0x6f, 0xf1, 0x61, 0x00

результатом является OK

UTF-8:

Исходный:

0x61, 0xc3, 0xb1, 0x6f, Реверс 0x00

:

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

результатом является мусор и недопустимая последовательность UTF-8

Обратный порядок байтов UTF-16:

Исходный:

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

первый байт будут рассматривать как NUL-разделитель. Никакое инвертирование не произойдет.

Прямой порядок байтов UTF-16:

Исходный:

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

второй байт будут рассматривать как NUL-разделитель. Результатом будет 0x61, 0x00, строка, содержащая символ.

11
ответ дан Juan Pablo Califano 23 November 2019 в 20:44
поделиться

В интересах полноты нужно указать, что существуют представления строк на различных платформах, по которым число байтов на символ варьируется в зависимости от символа. Олдскульные программисты назвали бы это DBCS (Двухбайтовый набор символов) . Современные программисты чаще всего встречаются с этим в UTF-8 (а также UTF-16 и другие). Также существует другая такая кодировка.

В любой из этих схем кодирования переменной ширины, простые алгоритмы, отправленные здесь ( зло , незло или иначе ), не работали бы правильно вообще! На самом деле они могли даже заставить строку становиться неразборчивой или даже недопустимая строка в той схеме кодирования. См. ответ Juan Pablo Califano для некоторых хороших примеров.

станд.:: реверс () потенциально все еще работал бы в этом случае, пока реализация Вашей платформы Стандартной Библиотеки C++ (в частности, строковые итераторы) правильно приняла это во внимание.

10
ответ дан Community 23 November 2019 в 20:44
поделиться
#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
4
ответ дан 23 November 2019 в 20:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: