কোনও ফাংশন থেকে সি স্ট্রিং ফিরিয়ে দেওয়া


109

আমি একটি ফাংশন থেকে একটি সি স্ট্রিং ফেরত দেওয়ার চেষ্টা করছি, তবে এটি কাজ করছে না। এখানে আমার কোড।

char myFunction()
{
    return "My String";
}

mainআমি এটিকে এভাবে ডাকছি:

int main()
{
  printf("%s", myFunction());
}

আমি এর জন্য আরও কিছু উপায় চেষ্টা করেছি myFunction, কিন্তু তারা কাজ করছে না। উদাহরণ স্বরূপ:

char myFunction()
{
  char array[] = "my string";
  return array;
}

দ্রষ্টব্য: আমার পয়েন্টার ব্যবহার করার অনুমতি নেই!

এই সমস্যা সম্পর্কে সামান্য পটভূমি:

কোন ফাংশন এটি খুঁজে পাচ্ছে যে এটি কোন মাস month উদাহরণস্বরূপ, যদি এটি 1 হয় তবে এটি জানুয়ারী, ইত্যাদি ফিরিয়ে দেয় etc.

সুতরাং যখনই মুদ্রণ যাচ্ছে, এটা এটা ভালো করছে: printf("Month: %s",calculateMonth(month));। এখন সমস্যাটি কীভাবে calculateMonthফাংশন থেকে সেই স্ট্রিংটি ফিরে আসবে ।


10
দুর্ভাগ্যক্রমে আপনার এই ক্ষেত্রে পয়েন্টার প্রয়োজন
নিক বেডফোর্ড 6

1
@ হাইতো ঠিক আছে আমি বিশ্বাস করি আমরা এখানে প্রাপ্তবয়স্ক এবং জানি যে এটির ফিরে আসা উচিত, এটি উদাহরণস্বরূপ
শৃঙ্খলা

3
return 0কেবল সি 99 (এবং সি ++) এ ডিফল্টরূপে বোঝানো হয়েছে তবে সি 90-এ নয়।
hrnt

1
তারপরে আপনি এটি করতে সক্ষম হবেন না, বোবা হ্যাকের পাশে যা সত্যিই কেবল ভেঙে যাওয়ার পয়েন্টার ম্যানিপুলেশনগুলি। পয়েন্টারগুলির একটি কারণ রয়েছে ...: |
GManNGG

উত্তর:


222

আপনার ফাংশনের স্বাক্ষর হওয়া দরকার:

const char * myFunction()
{
    return "My String";
}

পটভূমি:

এটি সি ও সি ++ এর পক্ষে এতটা মৌলিক, তবে আরও কিছুটা আলোচনা করা উচিত।

সি (& সি ++ বিষয়টির জন্য), একটি স্ট্রিং কেবল একটি শূন্য বাইট দ্বারা সমাপ্ত বাইটের একটি অ্যারে - সুতরাং স্ট্রিংয়ের এই বিশেষ স্বাদকে উপস্থাপন করতে "স্ট্রিং-শূন্য" শব্দটি ব্যবহৃত হয়। অন্যান্য ধরণের স্ট্রিং রয়েছে, তবে সি (& সি ++) এ, এই স্বাদটি ভাষা থেকেই স্বভাবগতভাবে বোঝা যায়। অন্যান্য ভাষা (জাভা, পাস্কাল ইত্যাদি) "আমার স্ট্রিং" বোঝার জন্য বিভিন্ন পদ্ধতি ব্যবহার করে।

আপনি যদি কখনও উইন্ডোজ এপিআই ব্যবহার করেন (যা সি ++ তে থাকে) তবে আপনি বেশ নিয়মিত প্যারামিটারগুলি দেখতে পাবেন যেমন: "এলপিসিএসআরটি এলপিএসএন নাম"। 'Sz' অংশটি 'স্ট্রিং-শূন্য' এর এই ধারণাটি উপস্থাপন করে: নাল (/ শূন্য) টার্মিনেটর সহ বাইটের অ্যারে।

ব্যাখ্যা:

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

স্মৃতি:

এর অর্থ হল "আমার স্ট্রিং" এর মতো একটি স্ট্রিং আসলে 9 + 1 (= 10!) বাইট ব্যবহার করে। আপনি অবশেষে কখন ডায়নামিকভাবে স্ট্রিং বরাদ্দ করতে পারেন তা জেনে রাখা গুরুত্বপূর্ণ।

সুতরাং, এই 'শূন্যের অবসান' না করে আপনার কোনও স্ট্রিং নেই। আপনার কাছে অক্ষরের একটি অ্যারে রয়েছে (এটি একটি বাফার নামেও পরিচিত) স্মৃতিতে ঘুরে।

তথ্য দীর্ঘায়ু:

ফাংশনটি এভাবে ব্যবহার করুন:

const char * myFunction()
{
    return "My String";
}

int main()
{
    const char* szSomeString = myFunction(); // Fraught with problems
    printf("%s", szSomeString);
}

... সাধারণত আপনাকে এলোমেলোভাবে ব্যতিক্রমহীন-ব্যতিক্রম / বিভাগের ত্রুটিগুলি এবং এর মতো করে বিশেষত 'রাস্তার নিচে' নিয়ে যায়।

সংক্ষেপে, যদিও আমার উত্তরটি সঠিক - 10 এর মধ্যে 9 বার আপনি কোনও প্রোগ্রামটি শেষ করবেন যা আপনি যদি এমনভাবে ব্যবহার করেন তবে ক্র্যাশ হবে, বিশেষত যদি আপনি মনে করেন যে এটি করা ভাল 'অনুশীলন'। সংক্ষেপে: এটি সাধারণত হয় না।

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

const char * myFunction(const char* name)
{
    char szBuffer[255];
    snprintf(szBuffer, sizeof(szBuffer), "Hi %s", name);
    return szBuffer;
}

অর্থাৎ আপনার প্রোগ্রাম কারণ কম্পাইলার (/ নাও হতে পারে হতে পারে) দ্বারা ব্যবহৃত মেমরি মুক্তি বিপর্যস্ত হবে szBufferসময় দ্বারা printf()main()বলা হয়। (আপনার সংকলকটিও আপনাকে আগে থেকেই এ জাতীয় সমস্যা সম্পর্কে সতর্ক করা উচিত))

স্ট্রিংগুলি ফেরত দেওয়ার দুটি উপায় রয়েছে যা এত তাড়াতাড়ি বাধা পাবে না।

  1. রিটার্নিং বাফার (স্থির বা গতিশীল বরাদ্দ) যা কিছু সময়ের জন্য বেঁচে থাকে। সি ++ তে std::stringডেটা-এর দীর্ঘায়ু (যা ফাংশনের রিটার্নের মান পরিবর্তন করতে হবে) পরিচালনা করতে 'সহায়ক ক্লাস' ব্যবহার করুন (উদাহরণস্বরূপ ), বা
  2. তথ্য সহ পূরণ করা হয় যে ফাংশন একটি বাফার পাস।

মনে রাখবেন যে সি তে পয়েন্টার ব্যবহার না করে স্ট্রিংগুলি ব্যবহার করা অসম্ভব আমি যেমন দেখিয়েছি যে সেগুলি সমার্থক। এমনকি টেমপ্লেট ক্লাস সহ সি ++ তেও সর্বদা পটভূমিতে বাফার (যা পয়েন্টার) ব্যবহৃত হচ্ছে।

সুতরাং, (এখন পরিবর্তিত প্রশ্ন) আরও ভাল উত্তর দিতে। (সরবরাহ করা যেতে পারে এমন বিভিন্ন 'অন্যান্য উত্তর' থাকার নিশ্চয়তা রয়েছে))

নিরাপদ উত্তর:

1 উদাহরণস্বরূপ, স্ট্যাটিকালি বরাদ্দ স্ট্রিংগুলি ব্যবহার করে:

const char* calculateMonth(int month)
{
    static char* months[] = {"Jan", "Feb", "Mar" .... };
    static char badFood[] = "Unknown";
    if (month<1 || month>12)
        return badFood; // Choose whatever is appropriate for bad input. Crashing is never appropriate however.
    else
        return months[month-1];
}

int main()
{
    printf("%s", calculateMonth(2)); // Prints "Feb"
}

এখানে 'স্ট্যাটিক' কী করে (অনেক প্রোগ্রামার এই ধরণের 'বরাদ্দ' পছন্দ করেন না) তা হ'ল স্ট্রিংগুলি প্রোগ্রামের ডেটা বিভাগে রাখে। এটি স্থায়ীভাবে বরাদ্দ।

আপনি যদি সি ++ এ যান তবে আপনি একই কৌশল ব্যবহার করবেন:

class Foo
{
    char _someData[12];
public:
    const char* someFunction() const
    { // The final 'const' is to let the compiler know that nothing is changed in the class when this function is called.
        return _someData;
    }
}

... তবে সহায়ক ক্লাসগুলি ব্যবহার করা সম্ভবত এটি সহজতর, যেমন std::stringআপনি যদি নিজের ব্যবহারের জন্য কোডটি লিখে থাকেন (এবং অন্যের সাথে ভাগ করে নেওয়ার জন্য কোনও লাইব্রেরির অংশ নয়)।

উদাহরণ 2, কলার-সংজ্ঞায়িত বাফার ব্যবহার করে:

চারপাশে স্ট্রিংগুলি পাস করার এটি আরও 'বোকা' way ফিরিয়ে দেওয়া ডেটা কলিং পার্টির কারসাজির বিষয় নয়। এটি হ'ল উদাহরণ 1 সহজেই একটি কলিং পার্টির দ্বারা আপত্তিজনকভাবে ব্যবহার করা যায় এবং আপনাকে অ্যাপ্লিকেশন ত্রুটিতে প্রকাশ করতে পারে। এইভাবে, এটি অনেক বেশি নিরাপদ (যদিও কোডের আরও লাইন ব্যবহার করে):

void calculateMonth(int month, char* pszMonth, int buffersize)
{
    const char* months[] = {"Jan", "Feb", "Mar" .... }; // Allocated dynamically during the function call. (Can be inefficient with a bad compiler)
    if (!pszMonth || buffersize<1)
        return; // Bad input. Let junk deal with junk data.
    if (month<1 || month>12)
    {
        *pszMonth = '\0'; // Return an 'empty' string
        // OR: strncpy(pszMonth, "Bad Month", buffersize-1);
    }
    else
    {
        strncpy(pszMonth, months[month-1], buffersize-1);
    }
    pszMonth[buffersize-1] = '\0'; // Ensure a valid terminating zero! Many people forget this!
}

int main()
{
    char month[16]; // 16 bytes allocated here on the stack.
    calculateMonth(3, month, sizeof(month));
    printf("%s", month); // Prints "Mar"
}

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

দাবি পরিত্যাগী:

আমি বেশ কয়েক বছর আগে অবসর নিয়েছিলাম এবং আমার সি এখন কিছুটা মরিচা। এই ডেমো কোডটি সমস্ত সি দিয়ে সঠিকভাবে সংকলন করা উচিত (যদিও এটি কোনও সি ++ কম্পাইলারের জন্য ঠিক আছে)।


2
প্রকৃতপক্ষে, ফাংশনটির একটি ফিরে আসা দরকার char *, কারণ সি এর স্ট্রিং আক্ষরিক ধরণের হয় char[]। তবে এগুলি অবশ্যই কোনওভাবেই সংশোধন করা উচিত নয়, সুতরাং প্রত্যাবর্তনকে const char*অগ্রাধিকার দেওয়া হয় (দেখুন সিকিওরকোডিং cerসার্ট.আর / কনফ্লুয়েন্স / এক্স / এমডব্লিউভি )। রিটার্নিংয়ের char *প্রয়োজন হতে পারে যদি স্ট্রিংটি কোনও উত্তরাধিকার বা বাইরের লাইব্রেরি ফাংশনে ব্যবহৃত হবে যা দুর্ভাগ্যক্রমে একটি char*যুক্তি হিসাবে প্রত্যাশা করে , এমনকি শক্ত এটি কেবল এটি থেকে পড়তে পারে। অন্যদিকে, সি ++ এর স্ট্রিং লিটারেলস const char[]টাইপ রয়েছে (এবং সি ++ 11 এর পরেও আপনি std::stringআক্ষরিক থাকতে পারে)।
টিমহানতে

17
আমার প্রিফিক্সটি @Cmroanirgo পাঠকের কাছে ঘোষণা করে যে এই ফাংশনটি ব্যবহারকারী দ্বারা তৈরি করা হয়েছিল। আমি এ জাতীয় প্রসঙ্গে ব্যবহার করা একেবারে যুক্তিযুক্ত বলে মনে করি।
কোয়ান্ট

4
এখানে অনুযায়ী: stackoverflow.com/questions/9970295/... , আপনি স্ট্রিং আক্ষরিক আসতে পারেন
giorgim

6
fraught with problems"ডেটার দৈর্ঘ্য" বিভাগে চিহ্নিত কোডটি আসলে পুরোপুরি বৈধ। স্ট্রিং আক্ষরিকের সি / সি ++ এ স্থির জীবনকাল থাকে। জিয়েরগি উপরে উল্লিখিত লিঙ্কটি দেখুন।
চেঙ্গিজ

1
@ সিএমরোয়ানিরগো স্ট্রিং আক্ষরিকাগুলি ফিরে আসা ভাল অনুশীলন এবং ভাল স্টাইল। এটি "সমস্যার দ্বারা পরিপূর্ণ নয়", এবং এটি 10 ​​টির মধ্যে 9 বার ক্রাশ হবে না: এটি কখনও ক্রাশ হবে না। এমনকি 80 এর দশকের সংকলক (কমপক্ষে আমি যেগুলি ব্যবহার করেছি) স্ট্রিং লিটারালগুলির সীমাহীন জীবনকালকে সঠিকভাবে সমর্থন করে। দ্রষ্টব্য: উত্তরটি সম্পাদনা করার বিষয়ে আপনি কী বোঝাতে চেয়েছিলেন তা আমি নিশ্চিত নই: আমি এখনও এটি দেখতে পেয়েছি এটি ক্র্যাশ হওয়ার ঝুঁকিতে রয়েছে।
সিসেস

12

এসি স্ট্রিংকে অক্ষরের অ্যারের পয়েন্টার হিসাবে সংজ্ঞায়িত করা হয়।

যদি আপনার পয়েন্টার না থাকে তবে সংজ্ঞা অনুসারে আপনার স্ট্রিং থাকতে পারে না।


আপনি একটি ফাংশনে একটি অ্যারের মধ্যে পাস করতে পারেন এবং তারপর যে শৃঙ্খলার করেঃ void foo( char array[], int length)। অবশ্যই, arrayহুডের নীচে একটি পয়েন্টার, তবে এটি "স্পষ্টভাবে" একটি পয়েন্টার নয়, এবং তাই এটি অ্যারে শেখার জন্য কারও পক্ষে আরও স্বজ্ঞাত হতে পারে তবে যিনি পয়েন্টারগুলি বেশ শিখেননি।
jvriesem

12

এই নতুন ফাংশনটি নোট করুন:

const char* myFunction()
{
    static char array[] = "my string";
    return array;
}

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

আরেকটি বিকল্প হ'ল স্তূপের স্ট্রিং বরাদ্দ করতে malloc ব্যবহার করা এবং তারপরে আপনার কোডের সঠিক অবস্থানগুলিতে বিনামূল্যে। এই কোডটি প্রেরণকারী এবং থ্রেডসেফ হবে।

মন্তব্যে উল্লিখিত হিসাবে, এটি একটি খুব খারাপ অভ্যাস, যেহেতু কোনও আক্রমণকারী তখন আপনার অ্যাপ্লিকেশনটিতে কোড ইনজেক্ট করতে পারে (তাকে / তাকে জিডিবি ব্যবহার করে কোডটি খুলতে হবে, তারপরে একটি ব্রেকপয়েন্ট) তৈরি করতে হবে এবং ফেরত ভেরিয়েবলের মান ওভারফ্লোতে পরিবর্তন করতে হবে এবং মজা সবে শুরু হয়)।

কলারকে মেমরি বরাদ্দের বিষয়ে পরিচালনা করতে আরও বেশি প্রস্তাব দেওয়া হয়। এই নতুন উদাহরণটি দেখুন:

char* myFunction(char* output_str, size_t max_len)
{
   const char *str = "my string";
   size_t l = strlen(str);
   if (l+1 > max_len) {
      return NULL;
   }
   strcpy(str, str, l);
   return input;
}

মনে রাখবেন যে একমাত্র সামগ্রী যা পরিবর্তিত হতে পারে তা হ'ল ব্যবহারকারী। আরেকটি পার্শ্ব প্রতিক্রিয়া - কমপক্ষে লাইব্রেরি দৃষ্টিকোণ থেকে এই কোডটি এখন থ্রেডসেফ। এই পদ্ধতিতে কলকারী প্রোগ্রামারকে যাচাই করা উচিত যে ব্যবহৃত মেমরি বিভাগটি থ্রেডসেফ।


2
এটি সাধারণত জিনিসগুলি যেতে একটি খারাপ উপায়। চর * পার্শ্ববর্তী কোড দ্বারা ম্যানিপুলেট করতে সক্ষম। এটি হল, আপনি এই জাতীয় জিনিসগুলি করতে পারেন: strcpy (myFunction (), "একটি সত্যিই দীর্ঘ স্ট্রিং"); এবং অ্যাক্সেস লঙ্ঘনের কারণে আপনার প্রোগ্রামটি ক্রাশ হবে।
সেমরোয়ানিরগো

"ব্যবহারকারী এক" এর কাছে কিছু অনুপস্থিত ।
পিটার মর্টেনসেন

8

আপনার সমস্যাটি ফাংশনের রিটার্ন টাইপের সাথে রয়েছে - এটি অবশ্যই হওয়া উচিত:

char *myFunction()

... এবং তারপরে আপনার মূল সূত্রটি কাজ করবে।

নোট করুন যে পয়েন্টারগুলিকে জড়িত না করে লাইন ধরে কোথাও আপনার সি স্ট্রিং থাকতে পারে না

এছাড়াও: আপনার সংকলক সতর্কতা চালু করুন। সুস্পষ্ট castালাই ছাড়াই সেই রিটার্ন লাইনে একটি রূপান্তর char *করার বিষয়ে আপনাকে সতর্ক করা উচিত ছিল char


1
আমি মনে করি স্বাক্ষরটি চরটি হওয়া উচিত * যেহেতু স্ট্রিংটি আক্ষরিক তবে আমি যদি ভুল না করি তবে সংকলক এটি গ্রহণ করবে।
লুক

5

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


3

আপনি কলারের মধ্যে অ্যারে তৈরি করতে পারবেন যা মূল কাজ, এবং অ্যারেটি কলিতে পাঠাতে যা আপনার মাই ফাংশন ()। সুতরাং myFunction অ্যারে মধ্যে স্ট্রিং পূরণ করতে পারেন। তবে আপনাকে আমার ফাংশনটি () হিসাবে ঘোষণা করতে হবে

char* myFunction(char * buf, int buf_len){
  strncpy(buf, "my string", buf_len);
  return buf;
}

এবং প্রধান ফাংশনে, আমার ফাংশনটি এইভাবে কল করা উচিত:

char array[51];
memset(array, 0, 51); /* All bytes are set to '\0' */
printf("%s", myFunction(array, 50)); /* The buf_len argument  is 50, not 51. This is to make sure the string in buf is always null-terminated (array[50] is always '\0') */

তবে, একটি পয়েন্টার এখনও ব্যবহৃত হয়।


2

আপনার ফাংশন রিটার্ন টাইপ একটি একক অক্ষর ( char)। আপনার চরিত্রের অ্যারের প্রথম উপাদানটিতে একটি পয়েন্টার ফিরে আসা উচিত। আপনি যদি পয়েন্টার ব্যবহার করতে না পারেন তবে আপনার ক্ষতি হবে। :(


2

বা এটি সম্পর্কে কীভাবে:

void print_month(int month)
{
    switch (month)
    {
        case 0:
            printf("January");
            break;
        case 1:
            printf("february");
            break;
        ...etc...
    }
}

এবং সেই মাসটিকে কল করুন যাতে আপনি অন্য কোথাও গণনা করেন।


1
+1 ওপি যা জিজ্ঞাসা করেছে তা নয়, তবে সম্ভবত কার্যভারটি আপনার কাছ থেকে প্রত্যাশা করে, যেহেতু তিনি পয়েন্টার ব্যবহার করতে পারবেন না।
ভিটিম.ইস

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

1

charশুধুমাত্র একটি একক বাইট অক্ষর। এটি অক্ষরের স্ট্রিং সংরক্ষণ করতে পারে না, বা এটি কোনও পয়েন্টারও নয় (যা আপনার সম্ভবত দৃশ্যমানভাবে থাকতে পারে না)। সুতরাং আপনি পয়েন্টার (যা char[]সিনট্যাকটিক চিনির জন্য) ব্যবহার না করেই আপনার সমস্যার সমাধান করতে পারবেন না ।


1

আপনি যদি সত্যিই পয়েন্টার ব্যবহার করতে না পারেন তবে এর মতো কিছু করুন:

char get_string_char(int index)
{
    static char array[] = "my string";
    return array[index];
}

int main()
{
    for (int i = 0; i < 9; ++i)
        printf("%c", get_string_char(i));
    printf("\n");
    return 0;
}

9 নম্বর ম্যাজিকটি ভয়াবহ এবং এটি ভাল প্রোগ্রামিংয়ের উদাহরণ নয়। কিন্তু আপনি ব্যপারটি ধরতে পেরেছেন. লক্ষ্য করুন যে পয়েন্টার এবং অ্যারেগুলি একই জিনিস (ধরণের), তাই এটি কিছুটা প্রতারণা।


সাধারণত আপনার যদি বাড়ির কাজের সমস্যার মতো সমাধানগুলি প্রয়োগ করতে হয় তবে আপনার প্রাথমিক অনুমানগুলি ভুল।
hrnt

1

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

const char* myFunction()
{

    return "My String";

}

constসিতে লিটারালগুলি সি হিসাবে লিটারাল হিসাবে সংশোধনযোগ্য নয় এমন সময় অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে অক্ষরে পাঠানোর সময় আপনার ধরণের যোগ্যতা অর্জন করা ভাল ।


0

আপনার ফাংশন প্রোটোটাইপ জানিয়েছে আপনার ফাংশনটি একটি চর ফিরিয়ে দেবে। সুতরাং, আপনি আপনার ফাংশন একটি স্ট্রিং ফিরে করতে পারবেন না।


0
char* myFunction()
{
    return "My String";
}

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


0

ফাংশন থেকে স্ট্রিং ফিরে

#include <stdio.h>

const char* greet() {
  return "Hello";
}

int main(void) {
  printf("%s", greet());
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.