आप उल्टे स्ट्रिंग को पकड़ने के लिए एक अलग बफर की आवश्यकता के बिना C या C ++ में एक स्ट्रिंग को कैसे रिवर्स करते हैं?
आप उल्टे स्ट्रिंग को पकड़ने के लिए एक अलग बफर की आवश्यकता के बिना C या C ++ में एक स्ट्रिंग को कैसे रिवर्स करते हैं?
जवाबों:
मानक एल्गोरिथ्म प्रारंभ / अंत तक पॉइंटर्स का उपयोग करना है, और जब तक वे बीच में मिलते हैं या पार नहीं करते हैं, तब तक वे अंदर की ओर चलते हैं। जाते ही स्वैप करें।
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- स्वैप का उपयोग किया है, इस लोकप्रिय प्रश्न के भविष्य के पाठकों के लाभ के लिए निश्चित है। XOR- स्वैप की अत्यधिक अनुशंसा नहीं की जाती है ; अपने कोड को कम कुशलता से पढ़ने और बनाने में मुश्किल है। आप Godbolt कंपाइलर एक्सप्लोरर पर देख सकते हैं कि asm लूप बॉडी कितना अधिक जटिल है जब x86-64 के लिए gcc -O3 के साथ xor- स्वैप संकलित किया जाता है।)
(यह XOR-स्वैप बात है। टिप्पणी करने के लिए ध्यान रखना है कि आप से बचना चाहिए स्वयं के साथ अदला-बदली, अगर क्योंकि *p
और *q
एक ही स्थान हैं आप एक ^ एक == 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;
}
उदाहरण:
$ ./strrev Räksmörgås ░▒▓○◔◑◕●
░▒▓○◔◑◕● ●◕◑◔○▓▒░
Räksmörgås sågrömskäR
./strrev verrts/.
#include <algorithm>
std::reverse(str.begin(), str.end());
C ++ में यह सबसे सरल तरीका है।
कर्निघन और रिची पढ़ें
#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;
}
}
s
को एक सरणी रूप में घोषित किया जाना चाहिए। दूसरे शब्दों में, char s[] = "this is ok"
बजाय इसके char *s="cannot do this"
कि एक स्ट्रिंग स्थिरांक में बाद के परिणाम संशोधित नहीं किए जा सकते हैं
जगह में एक स्ट्रिंग उल्टा (दृश्य):
गैर-बुराई सी, जहां सामान्य मामला है जहां स्ट्रिंग एक शून्य-समाप्त 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--;
}
}
int temp
, यह समाधान सबसे अच्छा लग रहा है। +1
!(*str)
हालांकि मैं व्यक्तिगत रूप से () को हटा दूंगा।
strchr()
खोज रहा है '\0'
। मैंने दोनों के बारे में सोचा। लूप की जरूरत नहीं।
आप std::reverse
C ++ मानक लाइब्रेरी से एल्गोरिथ्म का उपयोग करते हैं ।
कुछ समय हो गया है और मुझे याद नहीं है कि किस पुस्तक ने मुझे यह एल्गोरिथम सिखाया है, लेकिन मुझे लगा कि यह समझने में काफी सरल और सरल था:
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
हालांकि होना चाहिए ।
एसटीएल से एसटीडी :: रिवर्स विधि का उपयोग करें :
std::reverse(str.begin(), str.end());
तुम्हें पता है, "एल्गोरिथ्म" पुस्तकालय शामिल करना होगा #include<algorithm>
।
नोट std :: रिवर्स की सुंदरता है कि यह साथ काम करता है कि char *
तार और std::wstring
के रूप में बस के रूप में अच्छी तरह से एस std::string
एस
void strrev(char *str)
{
if (str == NULL)
return;
std::reverse(str, str + strlen(str));
}
*
टाइप करके नहीं डालते हैं और इसे नाम से डालते हैं। आश्चर्यजनक। मैं मानता हूँ कि मैं एक शुद्धतावादी के बारे में कुछ हूं लेकिन मैं हर बार कोड को देखता हूं जैसे मैं देखता हूं char* str;
।
यदि आप NULL टर्मिनेटेड बफ़र्स को उलटने की तलाश कर रहे हैं, तो यहां पोस्ट किए गए अधिकांश समाधान ठीक हैं। लेकिन, जैसा कि टिम फार्ले ने पहले ही बताया था, ये एल्गोरिदम केवल तभी काम करेंगे, जब यह मान लिया जाए कि यह एक स्ट्रिंग है जो शब्दार्थ बाइट्स (यानी सिंगल-बाइट स्ट्रिंग्स) का एक सरणी है, जो एक गलत धारणा है।
उदाहरण के लिए, स्ट्रिंग "año" (स्पेनिश में वर्ष)।
यूनिकोड कोड पॉइंट 0x61, 0xf1, 0x6f हैं।
सबसे अधिक इस्तेमाल किए जाने वाले कुछ एन्कोडिंग पर विचार करें:
लैटिन 1 / 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 बिग एंडियन:
मूल:
0x00, 0x61, 0x00, 0xf1, 0x00, 0x6f, 0x00, 0x00
पहले बाइट को एनयूएल-टर्मिनेटर के रूप में माना जाएगा। कोई उलटफेर नहीं होगा।
UTF-16 लिटिल एंडियन:
मूल:
0x61, 0x00, 0xf1, 0x00, 0x6f, 0x00, 0x00, 0x00
दूसरी बाइट को एनयूएल-टर्मिनेटर के रूप में माना जाएगा। परिणाम 0x61, 0x00, एक स्ट्रिंग होगा जिसमें 'a' वर्ण होगा।
पूर्णता के हित में, यह इंगित किया जाना चाहिए कि विभिन्न प्लेटफार्मों पर तार के प्रतिनिधित्व हैं जिसमें चरित्र के आधार पर प्रति चरित्र बाइट्स की संख्या भिन्न होती है । पुराने स्कूल प्रोग्रामर इसे DBCS (डबल बाइट कैरेक्टर सेट) के रूप में संदर्भित करेंगे । आधुनिक प्रोग्रामर आमतौर पर UTF-8 (साथ ही UTF-16 और अन्य) में इसका सामना करते हैं । इस तरह के अन्य एनकोडिंग भी हैं।
इन चर-चौड़ाई वाली एन्कोडिंग योजनाओं में से किसी में भी, यहां पर पोस्ट किए गए सरल एल्गोरिदम ( बुराई , गैर-बुराई या अन्यथा ) सही तरीके से काम नहीं करेंगे! वास्तव में, वे स्ट्रिंग को गैरकानूनी बनाने के लिए या उस एन्कोडिंग योजना में भी अवैध स्ट्रिंग का कारण बन सकते हैं। कुछ अच्छे उदाहरणों के लिए जुआन पाब्लो कैलिफानो का जवाब देखें ।
std :: रिवर्स () संभावित रूप से इस मामले में काम करेगा, जब तक कि आपके प्लेटफ़ॉर्म का मानक C ++ लाइब्रेरी (विशेष रूप से, स्ट्रिंग पुनरावृत्तियों) के कार्यान्वयन ने इसे ठीक से ध्यान में रखा हो।
एक और सी ++ तरीका (हालांकि मैं शायद एसटीडी का उपयोग करेगा: रिवर्स) () खुद को :) अधिक अभिव्यंजक और तेज होने के रूप में)
str = std::string(str.rbegin(), str.rend());
सी तरीका (अधिक या कम :)) और कृपया, स्वैपिंग के लिए 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);
एक पुस्तकालय समारोह कॉल की खोज शुरू होने से पहले किया जाएगा।
_mm_shuffle_epi8
(PSHUFB) 16B वेक्टर के क्रम को उल्टा कर सकता है, जिसे सही फेरबदल नियंत्रण वेक्टर दिया जाता है। यह शायद कुछ सावधानी से अनुकूलन के साथ लगभग विशेष रूप से AVX2 के साथ लगभग यादगार गति से चल सकता है।
char* beg = s-1
अपरिभाषित व्यवहार किया है (कम से कम अगर s
किसी सरणी के पहले तत्व को इंगित करता है, जो कि सबसे आम मामला है)। एक खाली स्ट्रिंग है, while (*++end);
तो अपरिभाषित व्यवहार s
है।
s-1
व्यवहार को परिभाषित किया है, भले ही s
किसी सरणी के पहले तत्व को इंगित करता हो, इसलिए यह वह है जो आपको मानक का समर्थन करने में सक्षम होना चाहिए।
#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
यदि आप GLib का उपयोग कर रहे हैं, तो इसके दो कार्य हैं, g_strreverse () और g_utf8_strreverse ()
मुझे एवगेनी के के एंड आर जवाब पसंद है। हालाँकि, पॉइंटर्स का उपयोग करके संस्करण देखना अच्छा है। अन्यथा, यह अनिवार्य रूप से समान है:
#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;
}
जगह में एक स्ट्रिंग रिवर्स करने के लिए पुनरावर्ती कार्य (कोई अतिरिक्त बफर, मॉलोक) नहीं।
लघु, सेक्सी कोड। खराब, खराब स्टैक का उपयोग।
#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;
}
char
स्टैक पर प्रत्येक को पुश करने से "जगह" के रूप में गिनती नहीं होती है। विशेष रूप से तब नहीं जब आप वास्तव में 4 * 8B प्रति वर्ण (64-बिट मशीन पर: 3 args + a return address) पर जोर दे रहे हों।
मेरा कोड साझा करें सी ++ सीखने वाले के रूप में, स्वैप () का उपयोग करने के विकल्प के रूप में, मैं विनम्रतापूर्वक टिप्पणी के लिए पूछ रहा हूं।
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--);
}
यदि आप ATL / MFC का उपयोग कर रहे हैं CString
, तो बस कॉल करें CString::MakeReverse()
।
अभी तक एक और:
#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);
}
#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");
}
मेरा उत्तर उनमें से अधिकांश के समान होगा, लेकिन कृपया यहां मेरा कोड खोजें।
//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;
}
मुझे लगता है कि स्ट्रिंग को उल्टा करने का एक और तरीका है। उपयोगकर्ता से इनपुट प्राप्त करें और इसे उल्टा करें।
void Rev() {
char ch;
cin.get(ch);
if(ch != '\n') {
Rev();
cout.put(ch);
}
}
यदि आपको इसे संग्रहीत करने की आवश्यकता नहीं है, तो आप इस तरह बिताए गए समय को कम कर सकते हैं:
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");
}
यहाँ सी। में मेरे लेने पर अभ्यास के लिए किया था और जितना संभव हो उतना संक्षिप्त करने की कोशिश की! आप कमांड लाइन के माध्यम से एक स्ट्रिंग दर्ज करते हैं, अर्थात ./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);
}
लेकिन मुझे लगता है कि 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()
लूप कंडीशन में और लूप बॉडी में कॉल दूर नहीं हो सकता है।
यहाँ सी + + (मेरी राय में) में एक स्ट्रिंग को रिवर्स करने का सबसे साफ, सबसे सुरक्षित, सबसे आसान तरीका है:
#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
कुछ भी अतिरिक्त करने की आवश्यकता नहीं है ।
#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;
}
यह स्ट्रिंग को उलटने के लिए सी भाषा में अनुकूलित कोड है ... और यह सरल है; बस काम करने के लिए एक सरल सूचक का उपयोग करें ...