স্টাড :: স্ট্রিং থেকে চর *


335

আমি একটি std :: স্ট্রিংকে একটি চর * বা চরের [] ডেটা ধরণে রূপান্তর করতে চাই ।

std::string str = "string";
char* chr = str;

ফলাফলগুলিতে: "ত্রুটি: 'std :: স্ট্রিং' কে 'চর' তে রূপান্তর করতে পারে না ..."

এটি করার জন্য কোন পদ্ধতি রয়েছে?

c++  string  char 

উত্তর:


671

এটি স্বয়ংক্রিয়ভাবে রূপান্তরিত হবে না (thankশ্বরকে ধন্যবাদ)। c_str()সি স্ট্রিংয়ের সংস্করণ পেতে আপনাকে পদ্ধতিটি ব্যবহার করতে হবে।

std::string str = "string";
const char *cstr = str.c_str();

মনে রাখবেন এটি একটি ফেরত দেয় const char *; আপনাকে সি-স্টাইলের স্ট্রিং দ্বারা পরিবর্তন করার অনুমতি নেই c_str()। আপনি যদি এটি প্রক্রিয়া করতে চান তবে আপনাকে প্রথমে এটি অনুলিপি করতে হবে:

std::string str = "string";
char *cstr = new char[str.length() + 1];
strcpy(cstr, str.c_str());
// do stuff
delete [] cstr;

বা আধুনিক সি ++ এ:

std::vector<char> cstr(str.c_str(), str.c_str() + str.size() + 1);

4
@ কেরেক এসবি: এটি একটি উদাহরণ ছিল, বাস্তব কোডটিতে একটি স্মার্ট পয়েন্টার ব্যবহার করবে বা সম্ভবত এই c_strউন্মাদনাটিকে পুরোপুরি এড়িয়ে চলবে ।
orlp

14
উত্তরটি বিশাল, অকার্যকর, অ-স্থানীয়, কাঁচা অ্যারে ব্যবহার করে এবং ব্যতিক্রমের সুরক্ষায় মনোযোগ প্রয়োজন। vectorডায়নামিক অ্যারেগুলির জন্য একটি মোড়ক হিসাবে সুনির্দিষ্টভাবে উদ্ভাবন করা হয়েছিল, সুতরাং এটি ব্যবহার না করা সেরা হারানো সুযোগের মতো বলে মনে হচ্ছে এবং সবচেয়ে খারাপভাবে সি ++ এর স্পিরিটের লঙ্ঘন।
কেরেক এসবি

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

8
আমি উত্তরটি হ্রাস পেয়েছি। এই উত্তরটি সত্যই কার্যকর নয় এবং এটি যে গ্রহণ করা হয়েছিল তা সত্যই সবচেয়ে দুর্ভাগ্যজনক। এই উত্তরটি পুরোপুরি ভাল সি ++ প্রোগ্রামিং অনুশীলন এবং ব্যতিক্রম সুরক্ষা উপেক্ষা করে এবং এর থেকেও অনেক উচ্চতর সমাধান পাওয়া যায়, এর কয়েকটি উত্তর এই প্রশ্নের অন্যান্য উত্তরে দেওয়া হয় (উদাহরণস্বরূপ ইল্ডার্নানের দেওয়া উত্তর যা ব্যবহার করে std::vector<char>)।
জেমস ম্যাকনেলিস

114
@ জেমস-ম্যাকনেলিস, আমি এই উত্তরটিকে সঠিক হিসাবে বেছে নিয়েছি কারণ এতে আমি যা চেয়েছিলাম ঠিক তা উত্তর দিয়েছিল ... আর নেই, কমও নয়। আপনি যা ভাবেন আমার কী করা উচিত তা আমি জিজ্ঞাসা করি নি, আপনি যা ভাবেন যে আমি করছি সেটার জন্য আমি আলাদা সমাধানের জন্য জিজ্ঞাসা করিনি, আমি ভাল অনুশীলনের জন্য জিজ্ঞাসা করি নি। আমি কী অবস্থায় কাজ করছি, আমার কোডটি কোথায় কার্যকর হচ্ছে এবং কোন অবস্থার অধীনে আপনার কোনও ধারণা নেই। কারও কারও পড়া শিখতে হবে, প্রশ্নগুলি বুঝতে হবে এবং আসলে কী জিজ্ঞাসিত হচ্ছে তার উত্তর দিতে হবে। এখানে দেখানোর দরকার নেই।

150

আরও বিশদ এখানে এবং এখানে আপনি ব্যবহার করতে পারেন

string str = "some string" ;
char *cstr = &str[0];

15
আমার বইতে এফডব্লিউআইডাব্লু, আসলে যে প্রশ্নটি করা হয়েছিল তার একমাত্র সঠিক উত্তর answer একটি স্ট্যান্ড :: স্ট্রিং সহজাতভাবে পরিবর্তনযোগ্য: এই স্ট্রিংয়ের বিষয়বস্তুগুলি সংশোধন করার মতো শোনার মতো লোকেরা শয়তানের কাজটি এই সত্যটি অনুপস্থিত বলে মনে হচ্ছে।
জে ফ্রিম্যান -সৌরিক-

2
হ্যাঁ, এটি সঠিক উত্তর। এটি নির্বোধ যে, ব্যবহারের ফ্রিকোয়েন্সিটি দেখে, এটি করার জন্য স্ট্যান্ডার্ট পদ্ধতি নেই, যেমন এমসফ্টের লকবফার।
এরিক অ্যারোনস্টি

1
আমি 0 থেকে 0u এ পরিবর্তন করেছি। কারণ কিছু সংকলক / গ্রন্থাগারগুলি অ্যান্ড
স্ট্রিং

আমার সন্দেহ হয় যখন str টি মুছে ফেলা হয়, চর সিএসটি নাল হয়ে যায়। সুতরাং আমি অনুমান করি এখানে কেবল মাত্র একটি পয়েন্টার চর পয়েন্টারকে দেওয়া হয়েছে। সুতরাং স্টারে চরে রূপান্তরটি আক্ষরিক অর্থে সম্পূর্ণ নয়। স্ট্রিং শুধুমাত্র চর * তে নির্দেশিত তবে এর মান রূপান্তরিত হয় না। আমি কি সঠিক???
সামিঠা চঠুরঙ্গ

5
মনে রাখবেন এটি কেবল সি ++ 11। পূর্ববর্তী সংস্করণগুলিতে অবিচ্ছিন্ন স্টোরেজ না থাকতে পারে বা সমাপ্ত
নালটি

40

আমার যদি সি ++ এর স্ট্রিং সামগ্রীর কোনও মিউটেবল কাঁচা অনুলিপি প্রয়োজন হয় তবে আমি এটি করতাম:

std::string str = "string";
char* chr = strdup(str.c_str());

এবং পরে:

free(chr); 

তাহলে আমি কেন অন্য কারোর মতো স্টাড :: ভেক্টর বা নতুন [] দিয়ে ঝাঁকুনি দিচ্ছি না? কারণ যখন আমার কোনও মিউটেবল সি-স্টাইলের কাঁচা চর * স্ট্রিং দরকার, তখন আমি সি কোডটি কল করতে চাই যা স্ট্রিং পরিবর্তন করে এবং সি কোডটি ফ্রি () দিয়ে স্টাফটিকে ডিলোকেট করে এবং ম্যালোক () (স্টার্টআপ ম্যালোক ব্যবহার করে) দিয়ে বরাদ্দ করে । সুতরাং যদি আমি কিছু ফাংশন এক্স আমার কাঁচা স্ট্রিং পাস সি লিখিত এটা পারে এটা যুক্তি উপর একটি বাধ্যতা বা এটির সাথে গাদা বরাদ্দ করেছে (উদাহরণস্বরূপ ফাংশন প্যারামিটার on realloc কল করতে চাইতে পারেন থাকেন)। তবে এটি অত্যন্ত সম্ভাবনা নয় যে এটি নতুন (] কিছু ব্যবহারকারী-নতুন সংজ্ঞায়িত) দিয়ে বরাদ্দকৃত যুক্তির প্রত্যাশা করবে!


কোথা strdupথেকে এসেছে তা আপনার ব্যাখ্যা করা উচিত ।
এলএফ

22

(এই উত্তরটি কেবলমাত্র C ++ 98 এর জন্য প্রযোজ্য))

দয়া করে, কোনও কাঁচা ব্যবহার করবেন না char*

std::string str = "string";
std::vector<char> chars(str.c_str(), str.c_str() + str.size() + 1u);
// use &chars[0] as a char*

1
আমার আসলে আজকের আগের মতো এরকম কিছু দরকার ছিল। আমি ভাবছিলাম, vector<char>(str.c_str(), str.c_str() + str.size() + 1)চরটি পয়েন্টারটি কোনও অস্থায়ী হিসাবে না দিয়ে বলা কি ঠিক হবে ?
কেরেক এসবি

1
@ কেরেক: হ্যাঁ, পরিবর্তিত বা ধ্বংস std::basic_string<>::c_str()হওয়া অবধি রিটার্নের মান কার্যকর হয় stringis এটি সূচিত করে যে এটি যতক্ষণ stringনা সংশোধন করা হয় ততক্ষণ পরবর্তী কলগুলিতে একই মানটি প্রদান করে ।
iljarn

2
@ ফ্রেন্ডজিস: এইভাবে ব্যবহার করার মতো কোনও গতি বা স্পেস ওভারহেড নেই vector। আর যদি কোনও RAII প্রক্রিয়া ব্যতীত ব্যতিক্রম-নিরাপদ কোড লিখতে হয় (যেমন, কাঁচা পয়েন্টার ব্যবহার করে), কোড জটিলতা এই সাধারণ ওয়ান-লাইনারের চেয়ে অনেক বেশি হবে।
iljarn

7
এটি একটি পৌরাণিক কাহিনী যা vectorএতে প্রচুর পরিমাণে ওভারহেড এবং জটিলতা রয়েছে। যদি আপনার প্রয়োজনীয়তাটি হয় যে আপনার একটি পরিবর্তনযোগ্য চর অ্যারে রয়েছে, তবে প্রকৃতপক্ষে চরগুলির একটি ভেক্টর আদর্শ সি ++ র‌্যাপারের চেয়ে অনেক বেশি। যদি আপনার প্রয়োজনীয়তাটি কেবল একটি কনস্ট-চর পয়েন্টারটির জন্য কল করে তবে কেবল ব্যবহার করুন c_str()এবং আপনার কাজ শেষ।
কেরেক এসবি

3
@ জিল্ডার্ন: আসলে এটি ছিল মূলত
অরবিট

15
  • আপনি যদি কেবল একই সামগ্রীর প্রতিনিধিত্ব করে একটি সি-স্টাইলের স্ট্রিং চান:

    char const* ca = str.c_str();
  • আপনি যদি নতুন বিষয়বস্তু সহ সি-স্টাইলের স্ট্রিং চান , তবে একটি উপায় (যে আপনি সংকলনের সময় স্ট্রিংয়ের আকারটি জানেন না) তা গতিশীল বরাদ্দ:

    char* ca = new char[str.size()+1];
    std::copy(str.begin(), str.end(), ca);
    ca[str.size()] = '\0';

    delete[]পরে এটি ভুলবেন না ।

  • আপনি যদি এর পরিবর্তে কোনও স্ট্যাটিকালি-বরাদ্দ, সীমিত দৈর্ঘ্যের অ্যারে চান:

    size_t const MAX = 80; // maximum number of chars
    char ca[MAX] = {};
    std::copy(str.begin(), (str.size() >= MAX ? str.begin() + MAX : str.end()), ca);

std::stringসাধারণ কারণ হিসাবে এটি করা প্রয়োজন সাধারণত ডিজাইনের গন্ধ হিসাবে স্পষ্টভাবে এই ধরণের রূপান্তরিত হয় না। আপনার সত্যই এটি প্রয়োজন তা নিশ্চিত করুন ।

আপনার যদি অবশ্যই একটি প্রয়োজন হয় তবে char*সবচেয়ে ভাল উপায় সম্ভবত:

vector<char> v(str.begin(), str.end());
char* ca = &v[0]; // pointer to start of vector

1
কেন &str.front(), &str.back()(যা সি ++ 03 তে উপস্থিত নেই) আরও সাধারণ str.begin()এবং এর পরিবর্তে str.end()?
আর্মেন ​​সিরুনিয়ান

1
কি str.begin(), বা এমনকি std::begin(str), পুনরুক্তি মত? আমি বিশ্বাস করি না যে stringমত স্মৃতিতে থাকার মতো কোনও বাধ্যবাধকতা আছে vector, নাকি আছে?
xtofl

1
@xtofl: আমি ইতিমধ্যে সেগুলিতে সম্পাদনা করেছি; এবং হ্যাঁ, সি ++ 11 হিসাবে একটি বাধ্যবাধকতা রয়েছে; এটি সি ++ 03 তে অন্তর্ভুক্ত ছিল।
লাইটনেস রেস

@xtofl: সি ++ 03 এ নেই। সি ++ ১১-এ আমাদের সেই গ্যারান্টিটি রয়েছে, সামনের () এবং পিছনে () ফাংশনগুলির সাথে, যা মূল
উত্তরটিতে

1
@ তোমালাক: তাদের আপনার প্রয়োজনের অপব্যবহার করা হয়েছিল &back() + 1, নয়&back()
আরমান তিরুনিয়ান

12

বোবোবোর উত্তরের মন্তব্য হিসাবে এটি আরও ভাল হবে তবে আমার কাছে এর জন্য কোন প্রতিনিধি নেই। এটি একই জিনিসটি সম্পাদন করে তবে আরও ভাল অনুশীলনের সাথে।

যদিও অন্যান্য উত্তরগুলি দরকারী, আপনার যদি কখনও বিনষ্ট ছাড়াই স্পষ্টত রূপান্তর std::stringকরতে হয় তবে আপনার বন্ধু।char*const_cast

std::string str = "string";
char* chr = const_cast<char*>(str.c_str());

নোট করুন যে এটি আপনাকে ডেটার একটি অনুলিপি দেবে না ; এটি আপনাকে স্ট্রিংয়ে একটি পয়েন্টার দেবে। সুতরাং, আপনি যদি কোনও উপাদান পরিবর্তন করেন তবে আপনি সংশোধন chrকরবেন str


7

ধরে নিই ইনপুট হিসাবে পাস করার জন্য আপনার কেবল সি স্টাইলের স্ট্রিং দরকার:

std::string str = "string";
const char* chr = str.c_str();

5

কঠোরভাবে পেডেন্টিক হওয়ার জন্য, আপনি "স্টাডি :: স্ট্রিংকে একটি চর * বা চর [টি] আকারে রূপান্তর করতে পারবেন না।"

অন্যান্য উত্তরগুলি যেমন দেখিয়েছে, আপনি স্টাড :: স্ট্রিংয়ের বিষয়বস্তু একটি চর অ্যারে অনুলিপি করতে পারেন, বা স্ট্যান্ড :: স্ট্রিংয়ের বিষয়বস্তুতে কন্সট চর তৈরি করতে পারেন যাতে আপনি এটি "সি স্টাইল" এ অ্যাক্সেস করতে পারেন ।

আপনি যদি স্টাডি :: স্ট্রিংয়ের বিষয়বস্তু পরিবর্তন করার চেষ্টা করছেন, স্ট্যান্ড :: স্ট্রিং টাইপটিতে আপনার সম্ভবত এটি করার জন্য প্রয়োজন হতে পারে এমন কিছু করার সমস্ত পদ্ধতি রয়েছে।

যদি আপনি এটি কোনও ফাংশনে পাস করার চেষ্টা করছেন যা একটি চর * লাগে, সেখানে স্ট্যান্ড :: স্ট্রিং :: সি_স্ট্রার () রয়েছে।


4

সম্পূর্ণতার জন্য, ভুলে যাবেন না std::string::copy()

std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];

str.copy(chrs, MAX);

std::string::copy()NUL সমাপ্ত হয় না। সি স্ট্রিং ফাংশনে ব্যবহারের জন্য যদি আপনাকে কোনও এনইউএল টার্মিনেটর নিশ্চিত করতে হয়:

std::string str = "string";
const size_t MAX = 80;
char chrs[MAX];

memset(chrs, '\0', MAX);
str.copy(chrs, MAX-1);

4

এখানে থেকে আরও একটি শক্তিশালী সংস্করণ Protocol Buffer

char* string_as_array(string* str)
{
    return str->empty() ? NULL : &*str->begin();
}

// test codes
std::string mystr("you are here");
char* pstr = string_as_array(&mystr);
cout << pstr << endl; // you are here

স্ট্রিংটি খালি আছে কিনা তা পরীক্ষা করার জন্য +1। আমি স্ট্রিংটি if (str[str.length()-1] != 0) str.push_back(0)
শূন্যরূপে

4

ওওপি শৈলীতে রূপান্তর

converter.hpp

class StringConverter {
    public: static char * strToChar(std::string str);
};

converter.cpp

char * StringConverter::strToChar(std::string str)
{
    return (char*)str.c_str();
}

ব্যবহার

StringConverter::strToChar("converted string")

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


3

বিকল্পভাবে, আপনি নীচে প্রদর্শিত হিসাবে লেখার চর * পেতে ভেক্টর ব্যবহার করতে পারেন;

//this handles memory manipulations and is more convenient
string str;
vector <char> writable (str.begin (), str.end) ;
writable .push_back ('\0'); 
char* cstring = &writable[0] //or &*writable.begin () 

//Goodluck  

এটি ভেক্টরের জন্য নতুন মেমরি বরাদ্দ করবে এবং তারপরে প্রতিটি অক্ষর অনুলিপি করবে। স্ট্যান্ড :: স্ট্রিং ইতিমধ্যে একটি ধারক, আপনি পাশাপাশি আপনার স্ট্রিংতে পুশ_ব্যাক (0) এবং করণীয় করতে পারেন [0]
গ্যাসপার্ড

3

আপনি এটির ব্যবহার করে এটি তৈরি করতে পারেন।

std::string str = "string";
std::string::iterator p=str.begin();
char* chr = &(*p);

শুভকামনা।


3

অনন্য_পিটার ব্যবহার করে অরল্পের চর * জবাবের একটি নিরাপদ সংস্করণ:

std::string str = "string";
auto cstr = std::make_unique<char[]>(str.length() + 1);
strcpy(cstr.get(), str.c_str());

3

একটি প্রাপ্ত const char *একটি থেকে std::stringব্যবহার c_str()সদস্য ফাংশন:

std::string str = "string";
const char* chr = str.c_str();

কোনওর char *থেকে নন-কনস্টেট পেতে std::stringআপনি data()সদস্য ফাংশনটি ব্যবহার করতে পারেন যা সি ++ 17 এর পরে থেকে কোনও অ-কনস্ট্যান্ট পয়েন্টার দেয়:

std::string str = "string";
char* chr = str.data();

ভাষার পুরানো সংস্করণগুলির জন্য, আপনি স্ট্রিংটি কোনও ভেক্টরে অনুলিপি করতে পরিসীমা নির্মাণ ব্যবহার করতে পারেন যা থেকে কোনও অ-স্থির পয়েন্টার পাওয়া যায়:

std::string str = "string";
std::vector<char> str_copy(str.c_str(), str.c_str() + str.size() + 1);
char* chr = str_copy.data();

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


2

এটিও কাজ করবে

std::string s;
std::cout<<"Enter the String";
std::getline(std::cin, s);
char *a=new char[s.size()+1];
a[s.size()]=0;
memcpy(a,s.c_str(),s.size());
std::cout<<a;  
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.