আপনি সি বা সি ++ এ স্থানে একটি স্ট্রিং কীভাবে বিপরীত করবেন?


173

বিপরীত স্ট্রিংটি ধরে রাখতে আলাদা বাফারের প্রয়োজন ছাড়াই আপনি কীভাবে সি বা সি ++ তে স্ট্রিংকে বিপরীত করবেন?


17
গৃহীত উত্তরের কোডটি ভীষণ ভুল । বিশদ জানতে stackoverflow.com/a/21263068/88656 দেখুন ।
এরিক লিপার্ট

উত্তর:


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করে, শেষ-সন্ধানকারী লুপের পরিবর্তে ব্যবহার করুন।

(সম্পাদকের দ্রষ্টব্য: এই উত্তরটি মূলত এই সাধারণ সংস্করণের জন্যও এক্সওআর-অদলবস্তু ব্যবহার করেছে this এই জনপ্রিয় প্রশ্নের ভবিষ্যতের পাঠকদের সুবিধার জন্য স্থির X এক্সওআর-অদলবদলকে খুব বেশি সুপারিশ করা হয় না ; আপনার কোডটি কম দক্ষতার সাথে সংকলন করে পড়া এবং তৈরি করা কঠিন You গডবোল্ট সংকলক এক্সপ্লোরারটিতে দেখতে পাবেন যে যখন জিসিসি-ও 3 দিয়ে x86-64-এর জন্য xor-swap সংকলন করা হয় তখন asm লুপের বডিটি আরও কত জটিল)


ঠিক আছে, ঠিক আছে, UTF-8 অক্ষর ঠিক করা যাক ...

(এটি এক্সওআর-অদলবদল জিনিস। খেয়াল রাখবেন যে আপনার নিজের সাথে স্ব্যাপিং এড়ানো অবশ্যই হবে , কারণ *pএবং যদি *qএকই অবস্থান হয় তবে এটি একটি zero a == 0 দিয়ে শূন্য করতে পারবেন X এক্সওর-অদলব দুটি পৃথক অবস্থানের উপর নির্ভর করে, এগুলি প্রতিটি অস্থায়ী সঞ্চয় হিসাবে ব্যবহার করে))

সম্পাদকের দ্রষ্টব্য: আপনি একটি টেম্প ভেরিয়েবল ব্যবহার করে একটি নিরাপদ ইনলাইন ফাংশন দিয়ে এসডাব্লুপিকে প্রতিস্থাপন করতে পারেন।

#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;
}
  • কেন, হ্যাঁ, যদি ইনপুটটি বোর্ক হয় তবে এটি স্থানের বাইরে আনন্দের সাথে স্যুইপ করবে।
  • ইউনিকোডে ভাঙচুর করার সময় দরকারী লিঙ্ক: http://www.macchiato.com/unicode/chart/
  • এছাড়াও, 0x10000 এরও বেশি ইউটিএফ -8 টি পরীক্ষা করা হয়নি (কারণ এটির জন্য আমার কোনও ফন্ট নেই বলে মনে হচ্ছে না, না হেক্সিডিটার ব্যবহার করার জন্য ধৈর্যও রয়েছে)

উদাহরণ:

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

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

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

./strrev verrts/.

162
অস্পষ্ট কোড প্রতিযোগিতার বাইরে এক্সওআর সোয়াপ ব্যবহার করার কোনও ভাল কারণ নেই।
ক্রিস কনওয়ে

28
আপনি মনে করেন "ইন-প্লেস" এর অর্থ "অতিরিক্ত মেমরি নেই", এমনকি অস্থায়ীদের জন্য ও (1) মেমরিটিও নয়? স্ট্রের স্ট্রের স্থান এবং রিটার্নের ঠিকানা সম্পর্কে কী?
ক্রিস কনওয়ে

55
@ বিল, এটি "ইন-প্লেস" এর সাধারণ সংজ্ঞা বলতে বোঝায় না। ইন-প্লেস অ্যালগরিদমগুলি অতিরিক্ত মেমরি ব্যবহার করতে পারে। তবে এই অতিরিক্ত মেমরির পরিমাণ অবশ্যই ইনপুটটির উপর নির্ভর করবে না - অর্থাত্ এটি অবশ্যই ধ্রুবক হতে হবে। অতএব, অতিরিক্ত সঞ্চয়স্থান ব্যবহার করে মানগুলি অদলবদল সম্পূর্ণভাবে জায়গায় in
কনরাড রুডল্ফ

19
জোর অদলবদল না যাওয়া পর্যন্ত এটিকে উত্সাহ দেওয়া নয়।
অ্যাডাম রোজেনফিল্ড

34
আধুনিক আউট-অফ-অর্ডার প্রসেসরের রেজিস্ট্রারের মাধ্যমে এক্সওআর অদলবদল সোয়াপিংয়ের চেয়ে ধীর।
প্যাট্রিক Schlüter

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

এটি সি ++ এর সহজতম উপায়।


6
সি ++ তে একটি স্ট্রিং স্ট্রিং ক্লাস দ্বারা প্রতিনিধিত্ব করা হয়। তিনি "চর তারকা" বা "চর বন্ধনী" চেয়েছিলেন না। উত্কৃষ্ট থাকুন, সি
জোকুন

10
@ ফ্রেডসবেন্ড, নির্বাচিত উত্তরের "হাস্যকর দীর্ঘ" সংস্করণ এমন একটি মামলা পরিচালনা করে যা এই সাধারণ উত্তরটি দেয় না - ইউটিএফ -8 ইনপুট। এটি সমস্যাটি সম্পূর্ণরূপে নির্দিষ্ট করার গুরুত্ব দেখায়। পাশাপাশি প্রশ্নটি কোড সম্পর্কে ছিল যা সি তেও কাজ করবে।
মার্ক র্যানসম

5
আপনি যদি কোনও ইউটিএফ -8 সচেতন স্ট্রিং ক্লাস ব্যবহার করেন (বা সম্ভবত স্টাডি :: বেসিক_স্ট্রিং সহ একটি utf-8 অক্ষর শ্রেণি) ব্যবহার করেন তবে এই উত্তরটি কেসটি পরিচালনা করবে handle এছাড়াও, প্রশ্নটি "সি বা সি ++" বলেছে, "সি এবং সি ++" নয়। সি ++ কেবলমাত্র "সি বা সি ++" হয়।
তাইউই

161

কার্নিগান এবং রিচি পড়ুন

#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
আমার আইফোনে পরীক্ষিত এটি প্রায় 15% দ্বারা কাঁচা পয়েন্টার ঠিকানা ব্যবহারের চেয়ে ধীর
jjxtra

3
ভেরিয়েবল "সি" এর কোন int এর পরিবর্তে চর হওয়া উচিত নয়?
পাঠ্যক্রম

17
এই উদাহরণে এটি লক্ষ করা গুরুত্বপূর্ণ যে স্ট্রিংটি sঅবশ্যই অ্যারে আকারে ঘোষণা করা উচিত। অন্য কথায়, এর char s[] = "this is ok"পরিবর্তে char *s="cannot do this"পরবর্তী ফলাফলগুলি পরিবর্তিত হতে পারে না এমন স্ট্রিং
ধ্রুবনে ঘটে

3
"দ্য গডফাদার" এর কাছে ক্ষমা চেয়ে .... "বন্দুক ছেড়ে দাও, কেএন্ডআর নিয়ে এস"। সি ধর্মাবলম্বী হিসাবে, আমি পয়েন্টারগুলি ব্যবহার করতাম, কারণ তারা এই সমস্যার জন্য আরও সহজ এবং আরও সোজা-এগিয়ে রয়েছে, তবে কোডটি সি #, জাভা ইত্যাদিতে কম পোর্টেবল হবে

2
@ এরিক এটি ও (লগ (এন)) সময়ে চলবে না। এটি ও (এন) এ চলে যদি আপনি স্ট্রিং দৈর্ঘ্যের n এর জন্য কোড সম্পাদন করে এমন চরিত্রের সংখ্যার কথা উল্লেখ করছেন, তবে n অদলবদল সম্পাদিত হয়। আপনি যদি আমরা সঞ্চালিত লুপের পরিমাণ সম্পর্কে কথা বলি তবে এটি এখনও O (n) - O (n / 2) সত্ত্বেও আপনি ধ্রুবকগুলিকে বিগ হে নোটেশনে ফেলে দেন।
স্টিফেন ফক্স

62

জায়গায় একটি স্ট্রিং বিপরীত (দৃশ্যায়ন):

জায়গায় একটি স্ট্রিং বিপরীত


শান্ত! আপনি এটি তৈরি করতে কী ব্যবহার করেছেন? আমি মনে করি উত্তরটি এর সাথে একটি লিঙ্ক অন্তর্ভুক্ত করে উন্নত হবে।
প্রাইফটান

এই অ্যালগরিদমের বাস্তবায়ন আসলে এই উত্তরে
কার্লফিলিপ

আপনি কি এটি কিছুটা ব্যাখ্যা করতে পারেন যদি চিত্রটির লিঙ্কটি মারা যায় তবে উত্তরটি অকেজো হবে না?
এসএস আন

41

স্ট্রিংটি নাল-টার্মিনেটেড charঅ্যারে হিসাবে সাধারণ ক্ষেত্রে ধরে নিয়ে অ-অশুভ সি C

#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) এর মতো কিছু ব্যবহার করতে পারবেন না; আমি জানি যে এটি ব্যবহারিকভাবে একই জিনিসটি করবে তবে আমি এটি আরও স্পষ্ট মনে করি।
পিটার কাহ্ন

যথেষ্ট ফর্সা। @ ইউভোটের উত্তরে অফ বাই ওয়ান ত্রুটি এড়াতে আমি চেষ্টা করেছিলাম (এবং ব্যর্থ হয়ে)।
ক্রিস কনওয়ে

সম্ভাব্য পারফরম্যান্সের উন্নতি হতে পারে পাশাপাশি int temp, এই সমাধানটি সেরা দেখাচ্ছে। +1
chux - মনিকা পুনরায় ইনস্টল করুন

@ chux-ReinstateMonica হ্যাঁ। ইহা সুন্দর. ব্যক্তিগতভাবে আমি !(*str)যদিও থেকে (গুলি) সরিয়ে ফেলব ।
প্রাইফটান

@ পিটারকাহ্ন হ্যাঁ বা strchr()অনুসন্ধান করছে '\0'। আমি দুজনের কথা ভেবেছি। লুপের দরকার নেই।
প্রাইফটান

35

আপনি std::reverseসি ++ স্ট্যান্ডার্ড লাইব্রেরি থেকে অ্যালগরিদম ব্যবহার করেন ।


14
স্ট্যান্ডার্ড টেম্পলেট লাইব্রেরি একটি প্রাক-মান শব্দ term সি ++ স্ট্যান্ডার্ড এটি উল্লেখ করে না, এবং প্রাক্তন এসটিএল উপাদানগুলি সি ++ স্ট্যান্ডার্ড লাইব্রেরিতে রয়েছে।
নেমানজা ত্রিফুনোভিচ

16
ঠিক আছে। আমি সর্বদা অবাক হই কেন এত লোক কেন এখনও এটিকে "এসটিএল" বলে ডাকে যদিও এটি কেবল বিষয়টি বিভ্রান্ত করার জন্য কাজ করে। সুন্দর হবে যদি আরও অনেক বেশি মানুষের তোমার মত এবং এটি শুধু "সি ++ স্ট্যান্ডার্ড লাইব্রেরী" বা STL কল এবং বলুন "স্ট্যান্ডার্ড লাইব্রেরী" :)
litb - জোহানেস Schaub

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কিছুটা হলেও হওয়া উচিত।
প্রাইফটান

24

STL থেকে বিপরীত পদ্ধতিটি ব্যবহার করুন :

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

আপনাকে "অ্যালগরিদম" লাইব্রেরি অন্তর্ভুক্ত করতে হবে #include<algorithm>,।


1
কোন লাইব্রেরি অন্তর্ভুক্ত করা প্রয়োজন?
ডন ক্রুইশঙ্ক

# অন্তর্ভুক্ত <ক্যালগরিদম> আমি এটি লিখতে ভুলে গিয়েছিলাম এবং উত্তরটি সম্পাদনা করেছিলাম তবে এটি সংরক্ষণ করা যায়নি, কেন নামটি অনুপস্থিত ছিল ..
ব্যবহারকারী2628229

যদিও এটি আমার উত্তরটিও হত, কেবল কৌতূহলী, কারণ ওপি "বাফার ছাড়াই বিপরীত স্ট্রিং ধরে রাখতে" জিজ্ঞাসা করেছিল (মূলত, ইন-প্লেস স্ব্যাপ), কীভাবে কেউ প্রমাণ করতে পারে যে এটি এমন করছে? কেউ কি কেবল ব্যাখ্যা করে যে এটি অভ্যন্তরীণভাবে std :: iter_swap <> ব্যবহার করে, উভয় প্রান্ত-বিন্দু থেকে মিড-পয়েন্ট পর্যন্ত বাফার করে? এছাড়াও, ওপিকে সি এবং সি উভয় জন্য জিজ্ঞাসা করা হয়েছে, এটি কেবল সি ++ এর জন্য (আমরা কেবল আশা করতে পারি <স্ট্রিং.ই.> এর স্ট্রাইভ () পদ্ধতি রয়েছে?)
হিদেকাএআইআই

21

নোট এসটিডি :: বিপরীত সৌন্দর্য এটি সঙ্গে কাজ করে যে char *স্ট্রিং এবং std::wstringযেমন ঠিক যেমন ভাল গুলি std::stringগুলি

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

1
একদিকে আমি বমি করতে চাই কারণ আপনি সি ++ ব্যবহার করেছেন তবে অন্যদিকে এটি এমন একটি সুন্দর, সুন্দর, একেবারে সুন্দর জিনিস যা কেউ সি ++ ব্যবহার করে তা *টাইপ করে না এবং নামটি দিয়ে দেয় see ওয়ান্ডারফুল। আমি স্বীকার করি আমি একজন পিউরিস্টের কিছু তবে আমি যতবার কোড দেখি ততবারই আমি ক্রিঞ্জ করি char* str;
প্রাইফটান

11

আপনি যদি নূন্যতম সমাপ্ত বাফারগুলির বিপরীত সন্ধান করছেন তবে এখানে পোস্ট করা বেশিরভাগ সমাধান ঠিক আছে। তবে, টিম ফারলে যেমন ইতিমধ্যে ইঙ্গিত করেছেন, এই আলগোরিদিমগুলি কেবল তখনই কাজ করবে যদি এটি ধরে নেওয়া বৈধ হয় যে কোনও স্ট্রিং শব্দার্থগতভাবে বাইটের একটি অ্যারে (অর্থাত্ সিঙ্গল-বাইট স্ট্রিং), যা একটি ভুল ধারণা, আমি মনে করি।

উদাহরণস্বরূপ, স্ট্রিং "আও" (স্প্যানিশ ভাষায়)।

ইউনিকোড কোড পয়েন্টগুলি 0x61, 0xf1, 0x6f।

সর্বাধিক ব্যবহৃত কয়েকটি এনকোডিংগুলি বিবেচনা করুন:

লাতিন 1 / আইসো -8859-1 (একক বাইট এনকোডিং, 1 টি অক্ষর 1 বাইট এবং বিপরীতে):

মূল:

0x61, 0xf1, 0x6f, 0x00

বিপরীত:

0x6f, 0xf1, 0x61, 0x00

ফলাফল ঠিক আছে

হল UTF-8:

মূল:

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

বিপরীত:

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

ফলাফলটি গীবির এবং একটি অবৈধ ইউটিএফ -8 সিকোয়েন্স

ইউটিএফ -16 বিগ এন্ডিয়ান:

মূল:

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

প্রথম বাইটটি NUL- টার্মিনেটর হিসাবে বিবেচিত হবে। কোন বিপরীত স্থান গ্রহণ করা হবে না।

ইউটিএফ -16 লিটল এন্ডিয়ান:

মূল:

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

দ্বিতীয় বাইটটি NUL- টার্মিনেটর হিসাবে বিবেচিত হবে। ফলাফলটি 0x61, 0x00 হবে, একটি স্ট্রিংটিতে 'এ' অক্ষর থাকবে।


std :: বিপরীত দ্বি-বাইট ইউনিকোড প্রকারের জন্য কাজ করবে যতক্ষণ আপনি wstring ব্যবহার করছেন।
অন্ধকার

আমি সি ++ এর সাথে খুব বেশি পরিচিত নই, তবে আমার ধারণা যে স্ট্রিংয়ের সাথে সম্পর্কিত কোনও সম্মানজনক স্ট্যান্ডার্ড লাইব্রেরি ফাংশন বিভিন্ন এনকোডিংগুলি পরিচালনা করতে সক্ষম হবে, তাই আমি আপনার সাথে একমত হই। "এই অ্যালগরিদম" দ্বারা, আমি এখানে পোস্ট করা এইড-হক বিপরীত ফাংশন বলতে চাইছি।
জুয়ান পাবলো ক্যালিফোানো

দুর্ভাগ্যক্রমে, স্ট্যান্ডার্ড সি ++ এ "স্ট্রিংগুলির সাথে সম্মানজনক ফাংশন" বলে কোনও জিনিস নেই।
জেম

@ উপগ্রহ যদি এটি কোনও সারোগেট জুটি উল্টায়, ফলাফল আর সঠিক হবে না। ইউনিকোড আসলে কোনও স্থির-প্রস্থের
চরসেট নয়

এই উত্তর সম্পর্কে আমি যা পছন্দ করি তা হ'ল এটি বাইটের প্রকৃত ক্রমগুলি দেখায় (যদিও অন্তরঙ্গতা কিছু হতে পারে - আহ, আমি দেখছি আপনি অবশ্যই এটি বিবেচনা করেছেন) এবং কীভাবে এটি সঠিক বা ভুল। তবে আমি মনে করি আপনি যদি কিছু প্রদর্শন করে এই কোডটি অন্তর্ভুক্ত করেন তবে উত্তরটির উন্নতি হবে।
প্রাইফটান

11

সম্পূর্ণতার স্বার্থে, এটি চিহ্নিত করা উচিত যে বিভিন্ন প্ল্যাটফর্মগুলিতে স্ট্রিংগুলির প্রতিনিধিত্ব রয়েছে যেখানে চরিত্রের উপর নির্ভর করে অক্ষর প্রতি বাইটের সংখ্যা পরিবর্তিত হয় । ওল্ড-স্কুল প্রোগ্রামাররা এটি ডিবিসিএস (ডাবল বাইট চরিত্র সেট) হিসাবে উল্লেখ করবে । আধুনিক প্রোগ্রামাররা সাধারণত ইউটিএফ -8 (পাশাপাশি ইউটিএফ -16 এবং অন্যদের) এ মুখোমুখি হয় । এছাড়াও অন্যান্য অন্যান্য এনকোডিং রয়েছে।

এই যেকোন ভেরিয়েবল-প্রস্থের এনকোডিং স্কিমগুলিতে, এখানে পোস্ট করা সাধারণ অ্যালগরিদমগুলি ( দুষ্ট , অ-মন্দ বা অন্যথায় ) সঠিকভাবে কাজ করবে না! আসলে, তারা এমনকি এনকোডিং স্কিমটিতে স্ট্রিংটিকে অবৈধ বা এমনকি একটি অবৈধ স্ট্রিংয়ের কারণ হতে পারে। কিছু ভাল উদাহরণের জন্য জুয়ান পাবলো ক্যালিফোনের উত্তর দেখুন ।

std :: বিপরীতমুখী () সম্ভাব্যভাবে এখনও এই ক্ষেত্রে কাজ করবে, যতক্ষণ না আপনার প্ল্যাটফর্মের স্ট্যান্ডার্ড সি ++ লাইব্রেরি প্রয়োগ করা হবে (বিশেষত স্ট্রিং পুনরাবৃত্তিকারী) এটি যথাযথভাবে বিবেচনায় নিয়েছে।


6
std :: বিপরীত এটিকে বিবেচনায় নেয় না। এটি মান_প্রকারের বিপরীতে। স্ট্যান্ডিং :: স্ট্রিংয়ের ক্ষেত্রে এটি চরের বিপরীত। চরিত্র নয়।
MSalters

বরং বলুন যে আমরা পুরানো স্কুল প্রোগ্রামাররা ডিবিসিএস জানি এবং ইউটিএফ -8 সম্পর্কেও জানি: কারণ আমরা সকলেই জানি যে প্রোগ্রামাররা যখন 'আরও একটি লাইন বলি তখন আমি নেশাগ্রস্থ ব্যক্তির মতো ' I'll আমি নিশ্চিত যে কিছু প্রোগ্রামার অবশেষে প্রস্থান করলো তবে খোলামেলা প্রোগ্রামিং আমার পক্ষে একটি আসক্তির মতো; আমি প্রোগ্রামিং না করে প্রত্যাহারগুলি পাই। এটি এখানে একটি ভাল পয়েন্ট যুক্ত করুন। আমি সি ++ পছন্দ করি না (এটির বেশ কিছুটা লেখার জন্যও আমি সত্যিই খুব চেষ্টা করেছি তবে এটি এখনও আমার পক্ষে নান্দনিকভাবে কমপক্ষে বলতে অপ্রয়োজনীয়) তাই আমি সেখানে মন্তব্য করতে পারি না তবে আপনি যাইহোক একটি ভাল বক্তব্য রেখেছেন একটি +1 আছে।
প্রাইফটান

5

আরও একটি সি ++ উপায় (যদিও আমি সম্ভবত সম্ভবত স্টাড :: বিপরীত () নিজেকে :) আরও প্রকাশিত এবং দ্রুত হিসাবে ব্যবহার করব)

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

সি উপায় (কম বা কম :)) এবং দয়া করে, অদলবদলের জন্য এক্সওআর কৌশল সম্পর্কে সতর্ক থাকুন, সংকলকরা কখনও কখনও এটি অপ্টিমাইজ করতে পারে না।

এই ক্ষেত্রে এটি সাধারণত অনেক ধীর হয়।

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স্ট্রিংটির শেষ সন্ধান করতে ব্যবহার করব , যদি এটি সম্ভবত দীর্ঘ হয়। একটি ভাল গ্রন্থাগার বাস্তবায়ন প্রতি পুনরাবৃত্তির জন্য 1 বাইটের চেয়ে দ্রুত অনুসন্ধান করতে সিমডি ভেক্টর ব্যবহার করবে। তবে খুব সংক্ষিপ্ত স্ট্রিংয়ের জন্য, while (*++end);একটি লাইব্রেরি ফাংশন কল অনুসন্ধান শুরু করার আগেই সম্পন্ন করা হবে।
পিটার

@ পিটারকর্ডস ভাল, সম্মত, স্ট্রেনকে পাঠযোগ্যতার জন্য যাইহোক ব্যবহার করা উচিত। দীর্ঘতর স্ট্রিংয়ের জন্য আপনার সর্বদা দৈর্ঘ্য যে কোনও ভাবেই কোনও ভেরিয়ালে রাখা উচিত। সিমডি-তে স্ট্রেন সাধারণত এই দাবি অস্বীকার করার সাথে একটি উদাহরণ হিসাবে দেওয়া হয়, এটি বাস্তব জীবনের আবেদন নয়, বা কোডটি লেখা হয়েছিল, কমপক্ষে এটি 5 বছর আগে ছিল। ;)
pprzemek

1
আপনি যদি সত্যিকারের সিপিইউগুলিতে এটি দ্রুত চালাতে চেয়েছিলেন তবে আপনি 16 বি খণ্ডে বিপরীত কাজ করতে সিমডি শ্যাফেলগুলি ব্যবহার করবেন। : পি যেমন x86 এর উপর, _mm_shuffle_epi8(পিএসএইচইউএফবি) সঠিক শ্যাফল কন্ট্রোল ভেক্টরকে দিয়ে একটি 16 বি ভেক্টরের ক্রমকে বিপরীত করতে পারে। এটি সম্ভবত কিছু সাবধানী অপ্টিমাইজেশান, বিশেষত AVX2 এর সাথে প্রায় ম্যাকপি গতিতে চলতে পারে।
পিটার কর্ডেস

char* beg = s-1অপরিবর্তিত আচরণ রয়েছে (কমপক্ষে sএকটি অ্যারের প্রথম উপাদানকে নির্দেশ করে, যা সর্বাধিক সাধারণ ঘটনা)। একটি খালি স্ট্রিং while (*++end);হলে অপরিজ্ঞাত আচরণ sহয় behavior
মেলপোমেন

@ পিপ্রজেমেক ওয়েল, আপনি দাবিটি করছেন যে s-1আচরণের সংজ্ঞা দিয়েছে এমনকি যদি sকোনও অ্যারের প্রথম উপাদানটির দিকেও লক্ষ্য করে, তবে আপনিই সেই ব্যক্তি, যিনি সমর্থনে মানটি উল্লেখ করতে সক্ষম হন।
মেলপোমেন

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
@ উওোট, স্ট্রাইকপি ব্যবহার করবেন না। কখনো। আপনার যদি strcpy ব্যবহারের মতো কিছু ব্যবহার করতে হয় strncpy। strcpy বিপজ্জনক। উপায় দ্বারা সি এবং সি ++ পৃথক সুবিধাসমূহ সহ দুটি পৃথক ভাষা। আমি মনে করি আপনি কেবল সি ++ এ উপলব্ধ শিরোলেখ ফাইলগুলি ব্যবহার করছেন তাই আপনার কি সত্যিকার অর্থে সি এর উত্তর দরকার?
ওনোরিও ক্যাটানাচি

6
প্রোগ্রামার যদি তার অ্যারের আকারের উপর নজর রাখতে পারে তবে স্ট্রিংপিপি পুরোপুরি নিরাপদ, অনেকে যুক্তি দেখান যে স্ট্রিংপিপি কম নিরাপদ কারণ এটি ফলাফলটি স্ট্রিংটি বাতিল করে দেওয়ার গ্যারান্টি দেয় না। যাই হোক না কেন, ইউভোটের এখানে স্ট্রাইকপি ব্যবহারের ক্ষেত্রে কোনও ভুল নেই।
রবার্ট গাম্বল

1
@ অ্যানরিও ক্যাটেনাকি, স্ট্রাইকপি বিপজ্জনক নয় যদি আপনি জানেন যে উত্সের স্ট্রিংটি গন্তব্য বাফারের অভ্যন্তরে ফিট হবে, যেমন উপরের কোডে দেওয়া ক্ষেত্রে রয়েছে। এছাড়াও, স্ট্রঙ্কপি শূন্য-পূরণ করে আকারের প্যারামিটারে বর্ণিত অক্ষরের সংখ্যা পর্যন্ত যদি বাম-ওভার ঘর থাকে, যা পছন্দসই নাও হতে পারে।
ক্রিস ইয়ং

3
যে কেউ সিআরপিপি সঠিকভাবে ব্যবহার করতে পারে না সে সি তে প্রোগ্রামিং করা উচিত নয়
রবার্ট গ্যাম্বলে

2
@ রবার্ট গ্যাম্বল, আমি সম্মত। তবে, যেহেতু আমি লোকদের সি তে প্রোগ্রামিং থেকে দূরে রাখার কোনও উপায় সম্পর্কে জানি না, তাদের দক্ষতা যাই হোক না কেন, আমি সাধারণত এটির বিরুদ্ধে প্রস্তাব দিই।
ওনোরিও ক্যাটানাচি


3

আমি ইভজেনির কেএন্ডআর উত্তরটি পছন্দ করি। যাইহোক, পয়েন্টার ব্যবহার করে একটি সংস্করণ দেখতে ভাল লাগছে। অন্যথায়, এটি মূলত একই:

#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

জায়গায় স্ট্রিংকে বিপরীতে ফেরাতে পুনরাবৃত্তির কাজ করুন (কোনও অতিরিক্ত বাফার, ম্যালোক নেই)।

সংক্ষিপ্ত, সেক্সি কোড। খারাপ, খারাপ স্ট্যাকের ব্যবহার।

#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
এটি একটি মজাদার সমাধান, আপনার প্রিন্টফের মতো কিছু ট্রেসিং যুক্ত করা উচিত ("% * s> [% d] রিভার্স_আর ('% সি',% পি = \"% এস \ ",% পি = \"% এস \ ") ; n ", গভীরতা," ", গভীরতা, ভাল, এস, (s? s:" নাল "), এন, (এন? এন:" নাল ")); শুরুতে এবং <শেষে
বেনোইট

প্রতিটি charস্ট্যাকের দিকে ঠেলাঠেলি "জায়গায়" হিসাবে গণনা করা হয় না। বিশেষত যখন আপনি অক্ষর প্রতি 4 * 8B চাপ দিচ্ছেন না (একটি 64-বিট মেশিনে: 3 টি আর্গ + একটি ফেরতের ঠিকানা)।
পিটার কর্ডস

মূল প্রশ্নটি হল "বিপরীত স্ট্রিংটি ধরে রাখতে আলাদা বাফারের প্রয়োজন ছাড়াই আপনি কীভাবে সি বা সি ++ তে একটি স্ট্রিং বিপরীত করবেন?" - 'জায়গায়' অদলবদলের কোনও প্রয়োজন ছিল না। এছাড়াও, এই সমাধানটি শুরু থেকেই খারাপ স্ট্যাক ব্যবহারের কথা উল্লেখ করে। অন্যান্য লোকের পড়ার বোধগম্যতার কারণে কি আমি ভোট দিচ্ছি?
সাইমন পেভেরেট

1
আমি এটিকে 'সেক্সি' বলব না তবে আমি বলব যে এটি প্রদর্শনী এবং নির্দেশমূলক। পুনরাবৃত্তি যদি সঠিকভাবে ব্যবহৃত হয় তবে এটি খুব মূল্যবান হতে পারে। তবে এটি উল্লেখ করা উচিত যে - সর্বশেষে আমি জানতাম - সি প্রতি সেও স্ট্যাকের প্রয়োজন হয় না; তবে এটি পুনরাবৃত্তি করে। যে কোনও উপায়ে এটি পুনরাবৃত্তির উদাহরণ যা সঠিকভাবে ব্যবহার করা গেলে খুব দরকারী এবং মূল্যবান হতে পারে। আমি মনে করি না যে আমি এটি কখনও স্ট্রিংকে বিপরীত করতে দেখেছি।
প্রাইফটান


1

আমার কোড শেয়ার করুন। সি ++ লার্নার হিসাবে অদলবদল () ব্যবহার করার বিকল্প হিসাবে আমি বিনীতভাবে মন্তব্য চাইছি asking

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

}

এটি পয়েন্টার গাণিতিক প্রদর্শন করে, অনেকটা আমার উত্তরের মতো, তবে এটি অদলবদলের সাথে সংযুক্ত করে। আমি বিশ্বাস করি এই উত্তরটি আসলে অনেক যোগ করে। কিছু সহজ টেক্সট বাক্স (আধুনিক অ্যাপ্লিকেশনগুলিতে আমি প্রায়শই দেখতে পেলাম) এর জন্য নির্ভরযোগ্যতা হিসাবে একটি বিলিয়ন লাইব্রেরি যুক্ত করার আগে আপনার এই ধরণের কোডটি বুঝতে সক্ষম হওয়া উচিত
স্টিফেন জে

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

সি ++ ল্যাম্বদা সহ:

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

সত্য তবে এটি কেবল বিপরীত ক্রমটি প্রিন্ট করে, তাই না? (আমি সি ++ ব্যবহার করি না তাই সম্ভবত .put () আমার মনে হয় যা তা করে না)।
প্রাইফটান

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

আমি একমাত্র উত্তর বলে মনে করি যার বাফার বা অস্থায়ী পরিবর্তনশীল নেই vari আমি স্ট্রিংয়ের দৈর্ঘ্য ব্যবহার করি, তবে অন্যেরা এটি করে যা মাথার জন্য আরও একটি যুক্ত করে (বনাম লেজ)। আমি মান অবিচ্ছিন্ন ফানকটি অদলবদল বা কোনও কিছুর মাধ্যমে ভেরিয়েবল সঞ্চয় করে নিচ্ছি। সুতরাং, আমি পয়েন্টার ম্যাথ এবং ইউটিএফ টাইপ লাইন আপ ধরে ধরে এই ছাপে আছি যে সম্ভবত এটিই কেবলমাত্র উত্তর যা আসলে প্রশ্নের উত্তর দেয়। যুক্ত প্রিন্টফ () গুলি বের করা যেতে পারে, আমি ফলাফলটি আরও ভাল দেখতে এটি করেছি। আমি এটি গতির জন্য লিখেছি। কোনও অতিরিক্ত বরাদ্দ বা বার নেই। বিপরীত স্ট্রিম () প্রদর্শনের জন্য সম্ভবত দ্রুততম অ্যালগরিদম
স্টিফেন জে

-3

সি তে আমার এটি গ্রহণ এখানে অনুশীলনের জন্য কি এবং যথাসম্ভব সংক্ষিপ্ত হওয়ার চেষ্টা করেছিল! আপনি কমান্ড লাইনের মাধ্যমে একটি স্ট্রিং প্রবেশ করেন, যেমন ./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
এটি একটি অপঠনযোগ্য গোলযোগ, তবে আপনি সম্ভবত সংক্ষিপ্ততম কোড ( কোড গল্ফ ) এর জন্য যাচ্ছেন না কারণ কিছু পরিবর্তনশীল নাম একাধিক চরিত্রের।
পিটার কর্ডস

-4

তবে আমি মনে করি এক্সওআর সোয়াপ অ্যালগরিদম সেরা ...

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()লুপের শর্তে এবং লুপের শরীরে কল আসতে পারে না optim
পিটার কর্ডস

-5

সি ++ এ (আমার মতে) স্ট্রিংটিকে বিপরীত করার সবচেয়ে পরিষ্কার, নিরাপদ এবং সহজতম উপায়টি এখানে:

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

এটি স্ট্রিংকে উল্টানোর জন্য সি ভাষায় অনুকূলিত কোড ... এবং এটি সহজ; কাজটি করার জন্য একটি সাধারণ পয়েন্টার ব্যবহার করুন ...


এটি একবারে স্ট্রিংয়ের জন্য একটি চর মুদ্রণ করে। এটি জায়গায় জায়গায় বিপরীত হয় না। এটি কোনও কারণ ছাড়াই ব্যবহারকারীর ইনপুটটির জন্য অপেক্ষা করে।
পিটার কর্ডস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.