কোনও ভেক্টর <int> কে স্ট্রিতে রূপান্তর করুন


95

আমার একটি vector<int>ধারক রয়েছে যার পূর্ণসংখ্যা রয়েছে (উদাহরণস্বরূপ {1,2,3,4}) এবং আমি ফর্মের একটি স্ট্রিংয়ে রূপান্তর করতে চাই

"1,2,3,4"

সি ++ এ করার সবচেয়ে পরিষ্কার উপায় কী? পাইথনে আমি এটি এটি করতাম:

>>> array = [1,2,3,4]
>>> ",".join(map(str,array))
'1,2,3,4'

4
ঘনিষ্ঠভাবে সম্পর্কিত: stackoverflow.com/questions/4850473/...
সিরো Santilli郝海东冠状病六四事件法轮功

উত্তর:


96

অবশ্যই পাইথনের মতো মার্জিত নয়, তবে সি ++ তে পাইথনের মতো তেমন কিছুই মার্জিত নয়।

আপনি একটি ব্যবহার করতে পারেন stringstream...

#include <sstream>
//...

std::stringstream ss;
for(size_t i = 0; i < v.size(); ++i)
{
  if(i != 0)
    ss << ",";
  ss << v[i];
}
std::string s = ss.str();

std::for_eachপরিবর্তে আপনি ব্যবহার করতে পারেন ।


আমি মনে করি আপনার মানে অ্যারে.সাইজ () v.size () নয়, না?
মার্ক ইলিয়ট

4
হ্যাঁ যাইহোক ভেক্টর বলা হয়।
ব্রায়ান আর বন্ডি

4
তা হওয়া উচিত std::string s = ss.str()। আপনি যদি একটি চান const char*, ব্যবহার করুন s.c_str()। (দ্রষ্টব্য, সংশ্লেষগতভাবে সঠিক হলেও, ss.str().c_str()আপনাকে এমন const char*একটি অস্থায়ী প্রতি নির্দেশ দেবে যা সম্পূর্ণ অভিব্যক্তি শেষে এসে দাঁড়াবে That এতে ব্যথা হয়েছে))
এসবিআই

4
শুধু স্ট্রিং.পেন্ড ব্যবহার করবেন না কেন?
বে

12
উত্তর ব্যতীত অসম্পূর্ণ#include <sstream>
20'2

44

Std :: for_each এবং lambda ব্যবহার করে আপনি আকর্ষণীয় কিছু করতে পারেন।

#include <iostream>
#include <sstream>

int main()
{
     int  array[] = {1,2,3,4};
     std::for_each(std::begin(array), std::end(array),
                   [&std::cout, sep=' '](int x) mutable {
                       out << sep << x; sep=',';
                   });
}

আমি লিখেছি এমন একটি ক্লাসের জন্য এই প্রশ্নটি দেখুন । এটি পেছনের কমা মুদ্রণ করবে না। এছাড়াও যদি আমরা ধরে নিই যে সি ++ 14 আমাদের এভাবে এলগোরিদমের বিস্তৃত সমতুল্য সরবরাহ করতে থাকবে:

namespace std {
   // I am assuming something like this in the C++14 standard
   // I have no idea if this is correct but it should be trivial to write if it  does not appear.
   template<typename C, typename I>
   void copy(C const& container, I outputIter) {copy(begin(container), end(container), outputIter);}
}
using POI = PrefexOutputIterator;   
int main()
{
     int  array[] = {1,2,3,4};
     std::copy(array, POI(std::cout, ","));
  // ",".join(map(str,array))               // closer
}

12
আমি মনে করি এটি পাইথনের যোগদানের সমপরিমাণ নয় - এটি শেষে একটি অতিরিক্ত "," সন্নিবেশ করবে।
1800 তথ্য

4
সমতুল্য নয় ঠিক যেমন মার্জিত (আসলে আমি আরও তাই মনে করি তবে এটি কেবল একটি মতামত)।
মার্টিন ইয়র্ক

21
স্পষ্টতই কমনীয়তা বিষয়ীয়। সুতরাং আপনি এবং অন্য দু'জন লোক যদি দীর্ঘতর, আরও পুনরাবৃত্ত কোড পছন্দ করেন যা কাজ করে না, তবে এটি আরও মার্জিত ;
স্টিভ

4
আপনি স্ট্রিং :: সাবস্ট্রি সদস্য ফাংশনটি ব্যবহার করে চূড়ান্ত কমা উপেক্ষা করতে পারেন। আপনার ফলাফলের পরিবর্তনশীলটিতে 0 থেকে n-1 পর্যন্ত স্ট্রিংটি বরাদ্দ করুন।
ড্যান

@ স্টিভ জেসোপ: আরও ভাল?
মার্টিন ইয়র্ক

24

আপনি স্টাড :: জমে ব্যবহার করতে পারেন। নিম্নলিখিত উদাহরণ বিবেচনা করুন

if (v.empty() 
    return std::string();
std::string s = std::accumulate(v.begin()+1, v.end(), std::to_string(v[0]),
                     [](const std::string& a, int b){
                           return a + ',' + std::to_string(b);
                     });

','হওয়া উচিত","
ম্যাট

4
@ ম্যাট ক্লাসটির অপারেটরের stringজন্য একটি ওভারলোড রয়েছে +যা অক্ষরগুলিও গ্রহণ করতে পারে। তাই ','ঠিক আছে।
পবন মঞ্জুনাথ

20

আর একটি বিকল্প হ'ল ব্যবহার std::copyএবং ostream_iteratorশ্রেণি:

#include <iterator>  // ostream_iterator
#include <sstream>   // ostringstream
#include <algorithm> // copy

std::ostringstream stream;
std::copy(array.begin(), array.end(), std::ostream_iterator<>(stream));
std::string s=stream.str();
s.erase(s.length()-1);

পাইথনের মতো সুন্দরও নয়। এই উদ্দেশ্যে, আমি একটি joinফাংশন তৈরি করেছি :

template <class T, class A>
T join(const A &begin, const A &end, const T &t)
{
  T result;
  for (A it=begin;
       it!=end;
       it++)
  {
    if (!result.empty())
      result.append(t);
    result.append(*it);
  }
  return result;
}

তারপরে এটি ব্যবহার করুন:

std::string s=join(array.begin(), array.end(), std::string(","));

আপনি জিজ্ঞাসা করতে পারেন কেন আমি পুনরাবৃত্তির মধ্যে পাস করেছি। ঠিক আছে, আসলে আমি অ্যারেটি বিপরীত করতে চেয়েছিলাম, তাই আমি এটি এটির মতো ব্যবহার করেছি:

std::string s=join(array.rbegin(), array.rend(), std::string(","));

আদর্শভাবে, আমি এমন বিন্দুতে টেমপ্লেট করতে চাই যেখানে এটি চরের প্রকারটি নির্ধারণ করতে পারে এবং স্ট্রিং-স্ট্রিম ব্যবহার করতে পারে, তবে আমি এখনও তা বুঝতে পারি নি।


যেহেতু এটি একটি মন্তব্যের পক্ষে অত্যধিক হবে, তাই আমি একটি উত্তর পোস্ট করেছি ( stackoverflow.com/questions/1430757/1432040#1432040 ) যা আপনার শেষ বাক্যে প্রদত্ত ধাঁধাটি সমাধান করার চেষ্টা করে।
এসবিআই

আপনার joinফাংশনটি ভেক্টরগুলির সাথেও ব্যবহার করা যেতে পারে? আপনি দয়া করে উদাহরণ দিতে পারেন, আমি সি ++ এ নতুন।
নোটিডার্ট

4
আপনি কি উত্তরের পুনরাবৃত্তিকে একটি পূর্বরূপে পরিবর্তন করতে পারবেন?
মিলি স্মিথ

14

বুস্ট এবং সি ++ 11 এর মাধ্যমে এটি এইভাবে অর্জন করা যেতে পারে:

auto array = {1,2,3,4};
join(array | transformed(tostr), ",");

ভাল প্রায়. এখানে সম্পূর্ণ উদাহরণ:

#include <array>
#include <iostream>

#include <boost/algorithm/string/join.hpp>
#include <boost/range/adaptor/transformed.hpp>

int main() {
    using boost::algorithm::join;
    using boost::adaptors::transformed;
    auto tostr = static_cast<std::string(*)(int)>(std::to_string);

    auto array = {1,2,3,4};
    std::cout << join(array | transformed(tostr), ",") << std::endl;

    return 0;
}

প্রিটোরিয়ানকে কৃতিত্ব ।

আপনি এই জাতীয় যে কোনও ধরণের হ্যান্ডেল করতে পারেন:

template<class Container>
std::string join(Container const & container, std::string delimiter) {
  using boost::algorithm::join;
  using boost::adaptors::transformed;
  using value_type = typename Container::value_type;

  auto tostr = static_cast<std::string(*)(value_type)>(std::to_string);
  return join(container | transformed(tostr), delimiter);
};

11

উদারতার অভাবের সাথে তার দ্বিতীয় সমাধানটি সম্পর্কে 1800 তথ্য দেওয়া মন্তব্যে দেওয়া ধাঁধাটি সমাধান করার চেষ্টা, প্রশ্নের উত্তর দেওয়ার চেষ্টা নয়:

template <class Str, class It>
Str join(It begin, const It end, const Str &sep)
{
  typedef typename Str::value_type     char_type;
  typedef typename Str::traits_type    traits_type;
  typedef typename Str::allocator_type allocator_type;
  typedef std::basic_ostringstream<char_type,traits_type,allocator_type>
                                       ostringstream_type;
  ostringstream_type result;

  if(begin!=end)
    result << *begin++;
  while(begin!=end) {
    result << sep;
    result << *begin++;
  }
  return result.str();
}

ওয়ার্ক অন অন মেশিন (টিএম)।


ভিজ্যুয়াল স্টুডিও 2013 টিপেডিফদের দ্বারা খুব বিভ্রান্ত হয়ে পড়ে। 2009 এ আপনি এটি জানতে পারতেন না
গ্রেট

@ জেস: আমি এখন 5 মিনিট ধরে এটাকে ঘুরে দেখছি, তবে ভিএস কী ভ্রমণ করতে পারে তা অনুধাবন করতে পারিনি। আপনি আরো নির্দিষ্ট হতে পারে?
sbi

আমি দুঃখিত, আমি মনে করি আমি << ওভারলোডগুলি ছাড়াই অবজেক্টগুলিতে যোগদানের চেষ্টা করেছি, যা আমি এখন বুঝতে পারি যে আপনার কোডের জন্য এটি অনুপযুক্ত। আমি আপনার কোডটি স্ট্রিংয়ের ভেক্টরের সাথে সংকলন না করতে পারি না। সাইড নোটে, ভিএস 2013 সম্প্রদায়টি "এক্সপ্রেস" সংস্করণগুলির থেকে পৃথক, বিনামূল্যে এবং বৈশিষ্ট্য-পূর্ণ উভয়ই।
গ্রেট

@ জেস: এটি স্ট্রিম করা যায় এমন কোনও ধরণের সাথে কাজ করা উচিত (অর্থাত্ operator<<ওভারলোড হয়েছে)। অবশ্যই, একটি টাইপ ছাড়াই operator<<খুব বিভ্রান্তিকর ত্রুটি বার্তা হতে পারে।
sbi

দুর্ভাগ্যবশত, এই কম্পাইল করে না: join(v.begin(), v.end(), ",")। যদি sepআর্গুমেন্টটি স্ট্রিং আক্ষরিক হয় তবে টেমপ্লেট আর্গুমেন্ট কর্তন সঠিক ফলাফল দেয় না । এই সমস্যার সমাধানের জন্য আমার প্রচেষ্টা । এছাড়াও আরও আধুনিক পরিসর-ভিত্তিক ওভারলোড সরবরাহ করে।
zett42

7

প্রচুর টেমপ্লেট / ধারণা। খনি যতটা জেনেরিক বা দক্ষ নয়, তবে আমার ঠিক একই সমস্যা ছিল এবং এটি ছোট এবং মিষ্টি জাতীয় হিসাবে মিশ্রণে ফেলে দিতে চেয়েছিলাম wanted এটি সংক্ষিপ্ত সংখ্যক লাইনে জয়ী হয়েছে ... :)

std::stringstream joinedValues;
for (auto value: array)
{
    joinedValues << value << ",";
}
//Strip off the trailing comma
std::string result = joinedValues.str().substr(0,joinedValues.str().size()-1);

4
সরলিক কোডের জন্য ধন্যবাদ। অতিরিক্ত অনুলিপিগুলি এড়াতে এবং কিছু সহজ পারফরম্যান্স লাভ পেতে তবে এটিকে "অটো &" তে পরিবর্তন করতে পারে।
মিলি স্মিথ

ব্যবহারের পরিবর্তে, শেষ চরিত্রটি সরিয়ে ফেলতে ব্যবহার করুন substr(...), pop_back()তখন অনেক বেশি পরিষ্কার এবং পরিষ্কার হয়ে যায়।
ifyalciner

4

আপনি যদি করতে চান তবে আপনি এর std::cout << join(myVector, ",") << std::endl;মতো কিছু করতে পারেন:

template <typename C, typename T> class MyJoiner
{
    C &c;
    T &s;
    MyJoiner(C &&container, T&& sep) : c(std::forward<C>(container)), s(std::forward<T>(sep)) {}
public:
    template<typename C, typename T> friend std::ostream& operator<<(std::ostream &o, MyJoiner<C, T> const &mj);
    template<typename C, typename T> friend MyJoiner<C, T> join(C &&container, T&& sep);
};

template<typename C, typename T> std::ostream& operator<<(std::ostream &o, MyJoiner<C, T> const &mj)
{
    auto i = mj.c.begin();
    if (i != mj.c.end())
    {
        o << *i++;
        while (i != mj.c.end())
        {
            o << mj.s << *i++;
        }
    }

    return o;
}

template<typename C, typename T> MyJoiner<C, T> join(C &&container, T&& sep)
{
    return MyJoiner<C, T>(std::forward<C>(container), std::forward<T>(sep));
}

দ্রষ্টব্য, এই সমাধানটি গৌণ বাফার তৈরির পরিবর্তে আউটপুট স্ট্রিমে সরাসরি যুক্ত হবে এবং কোনও প্রকারের সাথে কাজ করবে যার অপারেটর << একটি ostস্ট্রিমে onto

এটি যেখানে boost::algorithm::join()ব্যর্থ হয় সেখানেও কাজ করে , যখন আপনার vector<char*>পরিবর্তে একটি থাকে vector<string>


4
string s;
for (auto i : v)
    s += (s.empty() ? "" : ",") + to_string(i);

8
স্ট্যাক ওভারফ্লোতে স্বাগতম! যদিও এই কোডটি সমস্যার সমাধান করতে পারে, তবুও বিস্তারিতভাবে যুক্ত করা এবং এটি কীভাবে লোকেরা এই কোডটির টুকরোটি বুঝতে না পারে তার জন্য এটি কীভাবে কাজ করে তা ব্যাখ্যা করা ভাল।
কাগজ 1111

4
বর্তমান শীর্ষের উত্তরটি খুব বেশি বিস্তৃত নয় এবং এটি সবচেয়ে ছোট / পরিষ্কার কাজের উত্তর। std::stringstreamবড় অ্যারেগুলির মতো দক্ষ নয় কারণ এই উত্তরের stringstreamআকারের অ্যারের জন্য O (n.log) এর পরিবর্তে O (n.log (n)) পারফরম্যান্সের দিকে প্রত্যাশাজনকভাবে মেমরি বরাদ্দ করতে সক্ষম হবে n। এর stringstreamজন্য অস্থায়ী স্ট্রিংগুলি নাও তৈরি করতে পারে to_string(i)
আবেরাউদ

2

আমি 1800 এর উত্তর পছন্দ করি। তবে আমি প্রথম পুনরাবৃত্তিটি লুপের বাইরে সরিয়ে নিয়ে যাব কারণ যদি প্রথম বিবরণের পরে কেবলমাত্র বিবৃতিটি পরিবর্তন হয়

template <class T, class A>
T join(const A &begin, const A &end, const T &t)
{
  T result;
  A it = begin;
  if (it != end) 
  {
   result.append(*it);
   ++it;
  }

  for( ;
       it!=end;
       ++it)
  {
    result.append(t);
    result.append(*it);
  }
  return result;
}

আপনি যদি পছন্দ করেন তবে অবশ্যই এটি কম বিবৃতিতে কমে যেতে পারে:

template <class T, class A>
T join(const A &begin, const A &end, const T &t)
{
  T result;
  A it = begin;
  if (it != end) 
   result.append(*it++);

  for( ; it!=end; ++it)
   result.append(t).append(*it);
  return result;
}

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

পোস্ট ইনক্রিমেন্ট যতক্ষণ না আপনি ফিরে আসা অস্থায়ী মানটি ব্যবহার করেন ঠিক ততক্ষণ। উদাহরণস্বরূপ "রেজাল্ট.অ্যাপেন্ড (* এটি); ++ এটি;" "রেজাল্ট.অ্যাপেন্ড (* এটি ++)" এর মতো প্রায় সবসময় ব্যয়বহুল; দ্বিতীয়টিতে পুনরুক্তকারীর একটি অতিরিক্ত অনুলিপি রয়েছে।
আইয়েন

ওফস, আমি লুপের জন্য পোস্টের বর্ধন সন্ধান করেছি। কপি এবং পেস্ট ত্রুটি। আমি পোস্ট স্থির করেছি।
আইইন

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

4
@ এসবিআই: আমি সম্মত হয়েছি আমিও সবসময় পূর্বনির্ধারণের জন্য ডিফল্ট থাকি, দুর্বৃত্ত পোস্টিনগ্রেন্টটি লুপের জন্য কারও এলিসের অনুলিপি করে পরিবর্তন করে আসে। আমার প্রথম উত্তরে আমি ভেবেছিলাম আপনি "রেজাল্ট.অ্যাপেন্ড (* এটি ++)" এবং লুপের জন্য না হয়ে উদ্বিগ্ন। লুপে পোস্ট ইনক্রিমেন্ট দেখে আমি কিছুটা বিব্রত হয়েছিলাম। কিছু লোক পোস্ট বর্ধন খুব বেশি দূরে ব্যবহার না করার পরামর্শ অনুসরণ করে বলে মনে হয় এবং এটি যথাযথ হলেও এমনকি কখনই এটি ব্যবহার বা পরিবর্তন করে না। তবে আমি জানি এখন আপনি এই বিভাগে পড়েন না।
আয়ান

2

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

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

// Replace with your namespace //
namespace my {
    // Templated join which can be used on any combination of streams, iterators and base types //
    template <typename TStream, typename TIter, typename TSeperator>
    TStream& join(TStream& stream, TIter begin, TIter end, TSeperator seperator) {
        // A flag which, when true, has next iteration prepend our seperator to the stream //
        bool sep = false;                       
        // Begin iterating through our list //
        for (TIter i = begin; i != end; ++i) {
            // If we need to prepend a seperator, do it //
            if (sep) stream << seperator;
            // Stream the next value held by our iterator //
            stream << *i;
            // Flag that next loops needs a seperator //
            sep = true;
        }
        // As a convenience, we return a reference to the passed stream //
        return stream;
    }
}

এখন এটি ব্যবহার করতে, আপনি কেবল নীচের মতো কিছু করতে পারেন:

// Load some data //
std::vector<int> params;
params.push_back(1);
params.push_back(2);
params.push_back(3);
params.push_back(4);

// Store and print our results to standard out //
std::stringstream param_stream;
std::cout << my::join(param_stream, params.begin(), params.end(), ",").str() << std::endl;

// A quick and dirty way to print directly to standard out //
my::join(std::cout, params.begin(), params.end(), ",") << std::endl;

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


1

আমি একটি বর্ধিত যোগদানের সমর্থন যোগ করতে একটি সহায়ক শিরোনাম ফাইল তৈরি করেছি।

কেবলমাত্র আপনার সাধারণ শিরোনাম ফাইলে নীচের কোডটি যুক্ত করুন এবং যখন প্রয়োজন হয় তখন এটি অন্তর্ভুক্ত করুন।

ব্যবহারের উদাহরণ:

/* An example for a mapping function. */
ostream&
map_numbers(ostream& os, const void* payload, generic_primitive data)
{
    static string names[] = {"Zero", "One", "Two", "Three", "Four"};
    os << names[data.as_int];
    const string* post = reinterpret_cast<const string*>(payload);
    if (post) {
        os << " " << *post;
    }
    return os;
}

int main() {
    int arr[] = {0,1,2,3,4};
    vector<int> vec(arr, arr + 5);
    cout << vec << endl; /* Outputs: '0 1 2 3 4' */
    cout << join(vec.begin(), vec.end()) << endl; /* Outputs: '0 1 2 3 4' */
    cout << join(vec.begin(), vec.begin() + 2) << endl; /* Outputs: '0 1 2' */
    cout << join(vec.begin(), vec.end(), ", ") << endl; /* Outputs: '0, 1, 2, 3, 4' */
    cout << join(vec.begin(), vec.end(), ", ", map_numbers) << endl; /* Outputs: 'Zero, One, Two, Three, Four' */
    string post = "Mississippi";
    cout << join(vec.begin() + 1, vec.end(), ", ", map_numbers, &post) << endl; /* Outputs: 'One Mississippi, Two mississippi, Three mississippi, Four mississippi' */
    return 0;
}

দৃশ্যের পিছনে কোড:

#include <iostream>
#include <vector>
#include <list>
#include <set>
#include <unordered_set>
using namespace std;

#define GENERIC_PRIMITIVE_CLASS_BUILDER(T) generic_primitive(const T& v) { value.as_##T = v; }
#define GENERIC_PRIMITIVE_TYPE_BUILDER(T) T as_##T;

typedef void* ptr;

/** A union that could contain a primitive or void*,
 *    used for generic function pointers.
 * TODO: add more primitive types as needed.
 */
struct generic_primitive {
    GENERIC_PRIMITIVE_CLASS_BUILDER(int);
    GENERIC_PRIMITIVE_CLASS_BUILDER(ptr);
    union {
        GENERIC_PRIMITIVE_TYPE_BUILDER(int);
        GENERIC_PRIMITIVE_TYPE_BUILDER(ptr);
    };
};

typedef ostream& (*mapping_funct_t)(ostream&, const void*, generic_primitive);
template<typename T>
class Join {
public:
    Join(const T& begin, const T& end,
            const string& separator = " ",
            mapping_funct_t mapping = 0,
            const void* payload = 0):
            m_begin(begin),
            m_end(end),
            m_separator(separator),
            m_mapping(mapping),
            m_payload(payload) {}

    ostream&
    apply(ostream& os) const
    {
        T begin = m_begin;
        T end = m_end;
        if (begin != end)
            if (m_mapping) {
                m_mapping(os, m_payload, *begin++);
            } else {
                os << *begin++;
            }
        while (begin != end) {
            os << m_separator;
            if (m_mapping) {
                m_mapping(os, m_payload, *begin++);
            } else {
                os << *begin++;
            }
        }
        return os;
    }
private:
    const T& m_begin;
    const T& m_end;
    const string m_separator;
    const mapping_funct_t m_mapping;
    const void* m_payload;
};

template <typename T>
Join<T>
join(const T& begin, const T& end,
     const string& separator = " ",
     ostream& (*mapping)(ostream&, const void*, generic_primitive) = 0,
     const void* payload = 0)
{
    return Join<T>(begin, end, separator, mapping, payload);
}

template<typename T>
ostream&
operator<<(ostream& os, const vector<T>& vec) {
    return join(vec.begin(), vec.end()).apply(os);
}

template<typename T>
ostream&
operator<<(ostream& os, const list<T>& lst) {
    return join(lst.begin(), lst.end()).apply(os);
}

template<typename T>
ostream&
operator<<(ostream& os, const set<T>& s) {
    return join(s.begin(), s.end()).apply(os);
}

template<typename T>
ostream&
operator<<(ostream& os, const Join<T>& vec) {
    return vec.apply(os);
}

1

এখানে একটি জেনেরিক সি ++ 11 সমাধান রয়েছে যা আপনাকে করতে দেবে

int main() {
    vector<int> v {1,2,3};
    cout << join(v, ", ") << endl;
    string s = join(v, '+').str();
}

কোডটি হ'ল:

template<typename Iterable, typename Sep>
class Joiner {
    const Iterable& i_;
    const Sep& s_;
public:
    Joiner(const Iterable& i, const Sep& s) : i_(i), s_(s) {}
    std::string str() const {std::stringstream ss; ss << *this; return ss.str();}
    template<typename I, typename S> friend std::ostream& operator<< (std::ostream& os, const Joiner<I,S>& j);
};

template<typename I, typename S>
std::ostream& operator<< (std::ostream& os, const Joiner<I,S>& j) {
    auto elem = j.i_.begin();
    if (elem != j.i_.end()) {
        os << *elem;
        ++elem;
        while (elem != j.i_.end()) {
            os << j.s_ << *elem;
            ++elem;
        }
    }
    return os;
}

template<typename I, typename S>
inline Joiner<I,S> join(const I& i, const S& s) {return Joiner<I,S>(i, s);}

1

নিম্নলিখিত একটি সহজ এবং ব্যবহারিক উপায় উপাদান রূপান্তর হয় vectorএকটি থেকে string:

std::string join(const std::vector<int>& numbers, const std::string& delimiter = ",") {
    std::ostringstream result;
    for (const auto number : numbers) {
        if (result.tellp() > 0) { // not first round
            result << delimiter;
        }
        result << number;
    }
    return result.str();
}

আপনাকে করার প্রয়োজন #include <sstream>জন্য ostringstream


1

@Sbi এর জেনেরিক সমাধানে সীমাবদ্ধ নয় std::vector<int>বা একটি নির্দিষ্ট রিটার্নের ধরণের প্রকারের প্রসারকে প্রসারিত করা হচ্ছে । নীচে উপস্থাপিত কোডটি এভাবে ব্যবহার করা যেতে পারে:

std::vector<int> vec{ 1, 2, 3 };

// Call modern range-based overload.
auto str     = join( vec,  "," );
auto wideStr = join( vec, L"," );

// Call old-school iterator-based overload.
auto str     = join( vec.begin(), vec.end(),  "," );
auto wideStr = join( vec.begin(), vec.end(), L"," );

মূল কোডে, টেমপ্লেট আর্গুমেন্ট ছাড়ের বিভাজনটি স্ট্রিং আক্ষরিক (উপরের নমুনাগুলির মতো) হলে সঠিক রিটার্ন স্ট্রিং প্রকার উত্পাদন করতে কাজ করে না। এই ক্ষেত্রে, Str::value_typeফাংশন বডিটিতে টাইপডেফগুলি ভুল। কোডটি ধরে নেয় যা Strসর্বদা একটি ধরণেরstd::basic_string , তাই স্পষ্টতই এটি স্ট্রিং লিটারেলের জন্য ব্যর্থ।

এটি ঠিক করতে, নিম্নলিখিত কোডটি পৃথককারী আর্গুমেন্ট থেকে কেবলমাত্র অক্ষর টাইপকে হ্রাস করার চেষ্টা করে এবং এটি একটি ডিফল্ট রিটার্ন স্ট্রিং প্রকার উত্পাদন করতে ব্যবহার করে। এটি ব্যবহার করে অর্জন করা হয় boost::range_value, যা প্রদত্ত পরিসীমা প্রকার থেকে উপাদান প্রকারটি বের করে ।

#include <string>
#include <sstream>
#include <boost/range.hpp>

template< class Sep, class Str = std::basic_string< typename boost::range_value< Sep >::type >, class InputIt >
Str join( InputIt first, const InputIt last, const Sep& sep )
{
    using char_type          = typename Str::value_type;
    using traits_type        = typename Str::traits_type;
    using allocator_type     = typename Str::allocator_type;
    using ostringstream_type = std::basic_ostringstream< char_type, traits_type, allocator_type >;

    ostringstream_type result;

    if( first != last )
    {
        result << *first++;
    }
    while( first != last ) 
    {
        result << sep << *first++;
    }
    return result.str();
}

এখন আমরা সহজেই একটি পরিসীমা ভিত্তিক ওভারলোড সরবরাহ করতে পারি যা কেবল পুনরাবৃত্তি-ভিত্তিক ওভারলোডের দিকে এগিয়ে যায়:

template <class Sep, class Str = std::basic_string< typename boost::range_value<Sep>::type >, class InputRange>
Str join( const InputRange &input, const Sep &sep )
{
    // Include the standard begin() and end() in the overload set for ADL. This makes the 
    // function work for standard types (including arrays), aswell as any custom types 
    // that have begin() and end() member functions or overloads of the standalone functions.
    using std::begin; using std::end;

    // Call iterator-based overload.
    return join( begin(input), end(input), sep );
}

কলিরুতে লাইভ ডেমো


0

@ ক্যাপোন যেমন করেছে,

std::string join(const std::vector<std::string> &str_list , 
                 const std::string &delim=" ")
{
    if(str_list.size() == 0) return "" ;
    return std::accumulate( str_list.cbegin() + 1, 
                            str_list.cend(), 
                            str_list.at(0) , 
                            [&delim](const std::string &a , const std::string &b)
                            { 
                                return a + delim + b ;
                            }  ) ; 
}

template <typename ST , typename TT>
std::vector<TT> map(TT (*op)(ST) , const vector<ST> &ori_vec)
{
    vector<TT> rst ;
    std::transform(ori_vec.cbegin() ,
                  ori_vec.cend() , back_inserter(rst) , 
                  [&op](const ST& val){ return op(val)  ;} ) ;
    return rst ;
}

তারপরে আমরা নিম্নলিখিতগুলির মতো কল করতে পারি:

int main(int argc , char *argv[])
{
    vector<int> int_vec = {1,2,3,4} ;
    vector<string> str_vec = map<int,string>(to_string, int_vec) ;
    cout << join(str_vec) << endl ;
    return 0 ;
}

অজগর মত:

>>> " ".join( map(str, [1,2,3,4]) )

0

আমি এই জাতীয় কিছু ব্যবহার

namespace std
{

// for strings join
string to_string( string value )
{
    return value;
}

} // namespace std

namespace // anonymous
{

template< typename T >
std::string join( const std::vector<T>& values, char delimiter )
{
    std::string result;
    for( typename std::vector<T>::size_type idx = 0; idx < values.size(); ++idx )
    {
        if( idx != 0 )
            result += delimiter;
        result += std::to_string( values[idx] );
    }
    return result;
}

} // namespace anonymous

0

আমি @ এসবিআই এর উত্তর দিয়ে শুরু করেছি তবে বেশিরভাগ সময় পরিণতিযুক্ত স্ট্রিংটি একটি স্ট্রিমের সাথে পাইপিংয়ের সমাপ্তি ঘটায় নীচের সমাধানটি তৈরি করে যা মেমরির সম্পূর্ণ স্ট্রিং তৈরির ওভারহেড ছাড়াই কোনও স্ট্রিমে পাইপ করা যায়।

এটি নিম্নলিখিত হিসাবে ব্যবহৃত হয়:

#include "string_join.h"
#include <iostream>
#include <vector>

int main()
{
  std::vector<int> v = { 1, 2, 3, 4 };
  // String version
  std::string str = join(v, std::string(", "));
  std::cout << str << std::endl;
  // Directly piped to stream version
  std::cout << join(v, std::string(", ")) << std::endl;
}

যেখানে স্ট্রিং_জাইন.হ.

#pragma once

#include <iterator>
#include <sstream>

template<typename Str, typename It>
class joined_strings
{
  private:
    const It begin, end;
    Str sep;

  public:
    typedef typename Str::value_type char_type;
    typedef typename Str::traits_type traits_type;
    typedef typename Str::allocator_type allocator_type;

  private:
    typedef std::basic_ostringstream<char_type, traits_type, allocator_type>
      ostringstream_type;

  public:
    joined_strings(It begin, const It end, const Str &sep)
      : begin(begin), end(end), sep(sep)
    {
    }

    operator Str() const
    {
      ostringstream_type result;
      result << *this;
      return result.str();
    }

    template<typename ostream_type>
    friend ostream_type& operator<<(
      ostream_type &ostr, const joined_strings<Str, It> &joined)
    {
      It it = joined.begin;
      if(it!=joined.end)
        ostr << *it;
      for(++it; it!=joined.end; ++it)
        ostr << joined.sep << *it;
      return ostr;
    }
};

template<typename Str, typename It>
inline joined_strings<Str, It> join(It begin, const It end, const Str &sep)
{
  return joined_strings<Str, It>(begin, end, sep);
}

template<typename Str, typename Container>
inline joined_strings<Str, typename Container::const_iterator> join(
  Container container, const Str &sep)
{
  return join(container.cbegin(), container.cend(), sep);
}

0

আমি নিম্নলিখিত কোড লিখেছি। এটি সি # স্ট্রিং.জাইন ভিত্তিক। এটি স্টাডি :: স্ট্রিং এবং এসটিডি :: wstring এবং বিভিন্ন ধরণের ভেক্টরগুলির সাথে কাজ করে। (মন্তব্যে উদাহরণ)

এটিকে কল করুন:

 std::vector<int> vVectorOfIds = {1, 2, 3, 4, 5};

 std::wstring wstrStringForSQLIn = Join(vVectorOfIds, L',');

কোড:

// Generic Join template (mimics string.Join() from C#)
// Written by RandomGuy (stackoverflow) 09-01-2017
// Based on Brian R. Bondy anwser here:
// http://stackoverflow.com/questions/1430757/c-vector-to-string
// Works with char, wchar_t, std::string and std::wstring delimiters
// Also works with a different types of vectors like ints, floats, longs
template<typename T, typename D>
auto Join(const std::vector<T> &vToMerge, const D &delimiter)
{
    // We use std::conditional to get the correct type for the stringstream (char or wchar_t)
    // stringstream = basic_stringstream<char>, wstringstream = basic_stringstream<wchar_t>
    using strType =
        std::conditional<
        std::is_same<D, std::string>::value,
        char,
            std::conditional<
            std::is_same<D, char>::value,
            char,
            wchar_t
            >::type
        >::type;

    std::basic_stringstream<strType> ss;

    for (size_t i = 0; i < vToMerge.size(); ++i)
    {
        if (i != 0)
            ss << delimiter;
        ss << vToMerge[i];
    }
    return ss.str();
}

0

পূর্ণসংখ্যার ভেক্টরটিকে স্ট্রিংয়ে রূপান্তর করার জন্য এখানে একটি সহজ উপায়।

#include <bits/stdc++.h>
using namespace std;
int main()
{
    vector<int> A = {1, 2, 3, 4};
    string s = "";
    for (int i = 0; i < A.size(); i++)
    {
        s = s + to_string(A[i]) + ",";
    }
    s = s.substr(0, s.length() - 1); //Remove last character
    cout << s;
}

0

টেমপ্লেট ফাংশন ব্যবহার করে যোগ দিন

আমি আইটেমগুলিতে template functionযোগদানের জন্য একটি ব্যবহার vectorকরেছি, এবং ifকেবলমাত্র প্রথমে পেনাল্টিমেট আইটেমের মাধ্যমে পুনরাবৃত্তি করে অপ্রয়োজনীয় বিবৃতিটি সরিয়েছি vector, তারপরে শেষ আইটেমটিতে যোগ দিয়েছিfor লুপের । এটি যুক্ত স্ট্রিংয়ের শেষে অতিরিক্ত বিভাজক অপসারণ করার জন্য অতিরিক্ত কোডের প্রয়োজনীয়তাও মেনে চলে। সুতরাং, ifপুনরাবৃত্তিটি কমিয়ে দেয়ার মতো কোনও বিবৃতি নেই এবং অতিরিক্ত পর্যায়ে যাওয়ার প্রয়োজন নেই এমন কোনও অতিরিক্ত অতিরিক্ত বিভাজক নেই।

এই যোগ দেবার মার্জিত ফাংশন কল উত্পাদন করে vectorএর string,integer অথবা double, ইত্যাদি

আমি দুটি সংস্করণ লিখেছি: একটি স্ট্রিং দেয়; অন্যরা সরাসরি একটি স্ট্রিমে লেখেন।

#include <iostream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

// Return a string of joined vector items.
template<typename T>
string join(const vector<T>& v, const string& sep)
{
    ostringstream oss;
    const auto LAST = v.end() - 1;
    // Iterate through the first to penultimate items appending the separator.
    for (typename vector<T>::const_iterator p = v.begin(); p != LAST; ++p)
    {
        oss << *p << sep;
    }
    // Join the last item without a separator.
    oss << *LAST;
    return oss.str();
}

// Write joined vector items directly to a stream.
template<typename T>
void join(const vector<T>& v, const string& sep, ostream& os)
{
    const auto LAST = v.end() - 1;
    // Iterate through the first to penultimate items appending the separator.
    for (typename vector<T>::const_iterator p = v.begin(); p != LAST; ++p)
    {
        os << *p << sep;
    }
    // Join the last item without a separator.
    os << *LAST;
}

int main()
{
    vector<string> strings
    {
        "Joined",
        "from",
        "beginning",
        "to",
        "end"
    };
    vector<int> integers{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    vector<double> doubles{ 1.2, 3.4, 5.6, 7.8, 9.0 };

    cout << join(strings, "... ") << endl << endl;
    cout << join(integers, ", ") << endl << endl;
    cout << join(doubles, "; ") << endl << endl;

    join(strings, "... ", cout);
    cout << endl << endl;
    join(integers, ",  ", cout);
    cout << endl << endl;
    join(doubles, ";  ", cout);
    cout << endl << endl;

    return 0;
}

আউটপুট

Joined... from... beginning... to... end

1, 2, 3, 4, 5, 6, 7, 8, 9, 10

1.2; 3.4; 5.6; 7.8; 9

Joined... from... beginning... to... end

1, 2, 3, 4, 5, 6, 7, 8, 9, 10

1.2; 3.4; 5.6; 7.8; 9

0
#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v{{1,2,3,4}};
    std::string str;

    // ----->
    if (! v.empty())
    {
        str = std::to_string(*v.begin());
        for (auto it = std::next(v.begin()); it != v.end(); ++it)
            str.append("," + std::to_string(*it));
    }
    // <-----
    
    std::cout << str << "\n";
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.