Jak odwrócić ciąg znaków w C lub c++?
Jak odwrócić łańcuch w C lub C++ bez konieczności posiadania oddzielnego bufora do przechowywania odwróconego łańcucha?
30 answers
Evil 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;
}
(to jest XOR-swap. Należy pamiętać, że należy unikać zamiany z self, ponieważ A^a= = 0.)
OK, dobra, naprawmy znaki 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;
}
- dlaczego, tak, jeśli wejście jest borked, to wesoło Zamiana poza miejscem.
- użyteczny link przy wandalizowaniu w UNICODE: http://www.macchiato.com/unicode/chart /
- również UTF-8 ponad 0x10000 jest niesprawdzony (ponieważ nie mam żadnej czcionki w tym celu, ani cierpliwość do używania hexeditora)
Przykłady:
$ ./strrev Räksmörgås ░▒▓○◔◑◕●
░▒▓○◔◑◕● ●◕◑◔○▓▒░
Räksmörgås sågrömskäR
./strrev verrts/.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-08 10:31:31
#include <algorithm>
std::reverse(str.begin(), str.end());
Jest to najprostszy sposób w C++.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-22 03:51:05
Czytaj Kernighan i 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;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-16 19:16:28
Odwróć łańcuch w miejscu (wizualizacja):
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-11 21:12:20
Non-evil C, zakładając wspólny przypadek, gdzie łańcuch jest zakończoną znakiem nullchar
tablicą:
#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--;
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-13 19:56:40
Używasz std::reverse
algorytm z biblioteki standardowej C++.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-23 19:25:06
Minęło trochę czasu i nie pamiętam, która książka nauczyła mnie tego algorytmu, ale myślałem, że jest dość pomysłowy i prosty do zrozumienia:
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);
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-03 00:16:19
Użyj metody std:: reverse z STL:
std::reverse(str.begin(), str.end());
Będziesz musiał dołączyć bibliotekę "algorytm", #include<algorithm>
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-11 21:14:57
Zauważ, że piękno STD:: reverse polega na tym, że działa z char *
stringami i std::wstring
s tak samo dobrze jak std::string
S
void strrev(char *str)
{
if (str == NULL)
return;
std::reverse(str, str + strlen(str));
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-13 19:03:25
Jeśli szukasz odwracających buforów zakończonych znakiem NULL, większość rozwiązań tutaj zamieszczonych jest OK. Ale, jak już zauważył Tim Farley, algorytmy te będą działać tylko wtedy, gdy słuszne jest założenie, że ciąg znaków jest semantycznie tablicą bajtów( tj. ciągów jednobajtowych), co jest błędnym założeniem, jak sądzę.
Weźmy na przykład ciąg znaków " año " (rok w języku hiszpańskim).
Punkty kodu Unicode to 0x61, 0xf1, 0x6f.
Rozważ niektóre z najczęściej używanych kodowanie:
Latin1 / iso-8859-1 (kodowanie jednobajtowe, 1 znak to 1 bajt i odwrotnie):
Oryginalny:
0x61, 0xf1, 0x6f, 0x00
Rewers:
0x6f, 0xf1, 0x61, 0x00
Wynik jest OK
UTF-8:
Oryginalny:
0x61, 0xc3, 0xb1, 0x6f, 0x00
Rewers:
0x6f, 0xb1, 0xc3, 0x61, 0x00
Wynik jest bełkotem i nielegalną sekwencją UTF-8
UTF-16 Big Endian:
Oryginalny:
0x00, 0x61, 0x00, 0xf1, 0x00, 0x6f, 0x00, 0x00
Pierwszy bajt będzie traktowany jako nul-terminator. Nie będzie cofania.
UTF-16 Little Endian:
Oryginalny:
0x61, 0x00, 0xf1, 0x00, 0x6f, 0x00, 0x00, 0x00
Drugi bajt będzie traktowany jako NUL-terminator. Wynikiem będzie 0x61, 0x00, łańcuch zawierający znak 'a'.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-13 18:55:29
W trosce o kompletność należy zwrócić uwagę, że istnieją reprezentacje łańcuchów na różnych platformach, w których liczba bajtów na znak różne w zależności od charakteru. Staromodni Programiści nazwaliby to DBCS (Double Byte Character Set) . Większość programistów spotyka się z tym częściej w UTF-8 (a także UTF-16 i innych). Istnieją również inne tego typu kodowania.
W którymkolwiek z tych Schematy kodowania o zmiennej szerokości, proste algorytmy zamieszczone tutaj (, nie-złe lub w przeciwnym razie ) w ogóle nie działałoby poprawnie! W rzeczywistości mogą nawet spowodować, że ciąg znaków stanie się nieczytelny lub nawet nielegalny w tym schemacie kodowania. Zobacz odpowiedź Juana Pablo Califano dla kilku dobrych przykładów.
STD:: reverse () potencjalnie nadal będzie działać w tym przypadku, o ile Twoja platforma implementuje standardową bibliotekę C++ (w konkretne, Iteratory łańcuchowe) odpowiednio uwzględniły to.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:32
#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;
}
Ten kod produkuje to wyjście:
gnitset
a
cba
Jeśli używasz GLib, ma do tego dwie funkcje, g_strreverse () i G_utf8_strreverse()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-10-14 05:24:47
Inny sposób C++ (choć sam pewnie użyłbym std:: reverse ():) jako bardziej wyrazisty i szybszy)
str = std::string(str.rbegin(), str.rend());
The c way (mniej więcej :) ) i proszę, uważaj na sztuczkę XOR do zamiany, Kompilatory zazwyczaj nie mogą tego zoptymalizować.
W takim przypadku jest to zwykle znacznie wolniejsze.
char* reverse(char* s)
{
char* beg = s-1, *end = s, tmp;
while (*++end);
while (end-- > ++beg)
{
tmp = *beg;
*beg = *end;
*end = tmp;
}
return s;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-28 13:10:54
Podoba mi się odpowiedź Evgeny K & R. Jednak miło jest zobaczyć wersję używającą wskaźników. W przeciwnym razie jest to zasadniczo to samo:
#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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-17 16:06:40
Funkcja rekurencyjna odwracająca łańcuch znaków w miejscu (bez dodatkowego bufora, malloc).
Krótki, seksowny kod. Złe wykorzystanie stosu.#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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-22 10:39:46
Podziel się moim kodem. Jako uczący się C++, jako opcję użycia swap (), pokornie proszę o komentarze.
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--);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-11 21:13:49
Jeśli używasz ATL / MFC CString
, po prostu zadzwoń CString::MakeReverse()
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-27 17:47:57
Jeszcze jeden:
#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);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-08 19:40:47
#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");
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-30 05:28:15
Jeśli nie musisz go przechowywać, możesz skrócić czas spędzony w ten sposób:
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");
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-17 01:46:58
Z 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;
};
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-09 18:19:11
Moja odpowiedź byłaby podobna do większości z nich, ale proszę znaleźć mój kod tutaj.
//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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-11 19:06:23
Użycie std::reverse()
reverse(begin(str), end(str));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-12 01:05:14
Myślę, że jest inny sposób, aby odwrócić ciąg. Pobierz dane wejściowe od użytkownika i odwróć je.
void Rev()
{
char ch;
cin.get(ch);
if (ch != '\n')
{
Rev();
cout.put(ch);
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-05 12:22:53
Oto moje podejście do tego w C. zrobiłem to dla praktyki i starałem się być jak najbardziej zwięzły! Wpisujesz łańcuch za pomocą wiersza poleceń, czyli/program_name "enter string here"
#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);
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-02 13:34:33
Ale myślę, że algorytm XOR swap jest najlepszy...
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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-11 21:08:41
#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;
}
Jest to zoptymalizowany kod w języku C do odwracania ciągu znaków... I to jest proste; wystarczy użyć prostego wskaźnika, aby wykonać zadanie...
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-11 21:10:53
Oto najczystszy, najbezpieczniejszy i najłatwiejszy sposób odwrócenia ciągu znaków w C++ (moim zdaniem):
#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);
}
Alternatywą jest użycie std::swap
, ale lubię definiować własne funkcje - to ciekawe ćwiczenie i nie trzeba include
niczego dodatkowego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-16 01:13:42
/**
I am a boy -> boy a am I
*/
int main()
{
int i, j, n, temp, temp_i, cnt;
//char *array = "Samsung";
char array[1000];
char newarr[strlen(array)];
printf("Enter The String: \n");
gets(array);
for(i = (strlen(array)-1), n = 0, j = 0; i >= 0; i--)
{
if( array[i] != ' ')
{
n++;
}
else
{
temp = n;
temp_i = i;
for(n = 0; n <= temp; n++)
{
// i = i + 1;
newarr[j++] = array[i++];
}
i = temp_i;
n = 0;
}
if(i == 0)
{
newarr[j++] = ' ';
temp = n;
temp_i = i;
for(n = 0; n <= temp; n++)
{
// i = i + 1;
newarr[j++] = array[i++];
}
i = temp_i;
n = 0;
}
//newarr[j++] = array[i];
}
newarr[j] = '\0';
cnt = 0;
for(j = 0; j <= (strlen(newarr)-1); j++)//This is not required just do some R n D
{
newarr[j] = newarr[++cnt];
}
// printf("The first element is %c \n", newarr[1]);
puts(newarr);
return 0;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-12 10:37:21