সি ++ তে কোনও স্ট্রিংকে কীভাবে পার্স করবেন?


260

কোন স্ট্রিং (চর * হিসাবে দেওয়া) কে কোন আন্তঃকে পার্স করার সি ++ উপায় কী? দৃust় এবং স্পষ্ট ত্রুটি হ্যান্ডলিং একটি প্লাস ( শূন্য ফিরে আসার পরিবর্তে) )।


21
নিম্নলিখিতগুলির উদাহরণগুলির কয়েকটি সম্পর্কে কীভাবে: কোডেপ্রজেক্ট / কেবি / রেসিপস / টোকেনাইজার.এএসপিএক্স তারা খুব দক্ষ এবং কিছুটা মার্জিত

@ বেহ তৌ চেহ, আপনি যদি ভাবেন যে এটি পার্স করার ভাল উপায়, তবে দয়া করে একটি উত্তর হিসাবে পোস্ট করুন।
ইউজিন ইয়োকোটা

উত্তর:


164

নতুন সি ++ 11 এ এর ​​জন্য ফাংশন রয়েছে: স্টোই, স্টল, স্টল, স্টুল এবং আরও অনেক কিছু।

int myNr = std::stoi(myString);

এটি রূপান্তর ত্রুটিতে একটি ব্যতিক্রম ছুঁড়ে দেবে।

এমনকি এই নতুন ফাংশনগুলিতে এখনও ড্যান দ্বারা উল্লিখিত একই সমস্যা রয়েছে : তারা আনন্দের সাথে "11x" স্ট্রিংটিকে পূর্ণসংখ্যা "11" তে রূপান্তর করবে।

আরও দেখুন: http://en.cppreferences.com/w/cpp/string/basic_string/stol


4
তবে তারা তার চেয়ে যুক্তি স্বীকার করে, তাদের মধ্যে একটি আকারের বিন্দু হিসাবে এটি যে শূন্য না হলে প্রথম রূপান্তরিত চরিত্রটিতে সেট করা আছে
জারফ

হ্যাঁ, std :: stoi এর দ্বিতীয় প্যারামিটার ব্যবহার করে আপনি অবৈধ ইনপুট সনাক্ত করতে পারবেন। আপনাকে এখনও নিজের রূপান্তর ফাংশনটি রোল করতে হবে যদিও ...
সিসি।

গৃহীত উত্তর যেমনটি করেছে ঠিক তেমনি এই মানক ক্রিয়াকলাপগুলির সাথে যা আরও পরিষ্কার হবে, ইমো
Zharf

204

কী করবেন না

আমার পরামর্শের প্রথম অংশটি এখানে: এটির জন্য স্ট্রিংস্ট্রিম ব্যবহার করবেন না । প্রথমদিকে এটি ব্যবহার করা সহজ বলে মনে হচ্ছে, আপনি দৃust়তা এবং ভাল ত্রুটি পরিচালনা করতে চাইলে আপনাকে অনেক অতিরিক্ত কাজ করতে হবে।

এটি এমন একটি পদ্ধতির যা স্বজ্ঞাতভাবে মনে হয় এটির কাজ করা উচিত:

bool str2int (int &i, char const *s)
{
    std::stringstream ss(s);
    ss >> i;
    if (ss.fail()) {
        // not an integer
        return false;
    }
    return true;
}

এটি একটি বড় সমস্যা রয়েছে: str2int(i, "1337h4x0r")আনন্দের সাথে ফিরে আসবে trueএবং iমান পাবে 1337stringstreamরূপান্তর পরবর্তী কোনও অক্ষর নেই তা নিশ্চিত করে আমরা এই সমস্যাটি নিয়ে কাজ করতে পারি :

bool str2int (int &i, char const *s)
{
    char              c;
    std::stringstream ss(s);
    ss >> i;
    if (ss.fail() || ss.get(c)) {
        // not an integer
        return false;
    }
    return true;
}

আমরা একটি সমস্যা সমাধান করেছি, তবে এখনও আরও কয়েকটি সমস্যা রয়েছে।

স্ট্রিংয়ের সংখ্যাটি যদি বেস 10 না হয়? স্ট্রিমটিকে সঠিক মোডে সেট করে আমরা অন্যান্য ঘাঁটিগুলিকে সমন্বিত করার চেষ্টা করতে পারি (উদাঃss << std::hexরূপান্তরটি চেষ্টা করার আগে আমরা ) করার চেষ্টা করতে পারি। তবে এর অর্থ হ'ল কলকারীকে অবশ্যই একটি প্রাইমারি জানতে হবে যে নম্বরটি কী তা - এবং কলকারী কীভাবে এটি জানতে পারে? কলকারী এখনও জানে না নম্বরটি কী। এমনকি তারা জানে না যে হয়একটি সংখ্যা! কীভাবে তারা জানতে পারে যে এটি কী বেস? আমরা কেবলমাত্র আদেশ দিতে পারি যে আমাদের প্রোগ্রামগুলিতে সমস্ত সংখ্যার ইনপুটটি বেস 10 হতে হবে এবং হেক্সাডেসিমাল বা অষ্টাল ইনপুটটিকে অবৈধ হিসাবে প্রত্যাখ্যান করতে হবে। তবে এটি খুব নমনীয় বা মজবুত নয়। এই সমস্যার কোনও সহজ সমাধান নেই। আপনি প্রতিটি বেসের জন্য একবার রূপান্তর চেষ্টা করতে পারবেন না, কারণ দশমিক রূপান্তরটি সর্বদা অষ্টাল সংখ্যার (অগ্রণী শূন্যের সাথে) সফল হবে এবং অষ্টাল রূপান্তরটি কিছু দশমিক সংখ্যার জন্য সফল হতে পারে। সুতরাং এখন আপনাকে একটি শীর্ষস্থানীয় শূন্যের জন্য পরীক্ষা করতে হবে। কিন্তু অপেক্ষা করো! হেক্সাডেসিমাল সংখ্যাগুলি একটি শূন্য শূন্যের সাথেও শুরু করতে পারে (0x ...)। দীর্ঘশ্বাস.

আপনি যদি উপরোক্ত সমস্যাগুলি মোকাবেলা করতে সফল হন, তবুও আরও একটি বড় সমস্যা রয়েছে: যদি কলকারীকে খারাপ ইনপুট (যেমন "123foo") এবং যে কোনও সংখ্যার int(যেমন "4000000000" এর সীমার বাইরে থাকে তার মধ্যে পার্থক্য করার প্রয়োজন হয় তবে কী হবে? 32-বিট int)? সাথে stringstream, এই পার্থক্য করার কোনও উপায় নেই। রূপান্তরটি সফল হয়েছে কি ব্যর্থ হয়েছে তা আমরা কেবল জানি। যদি এটি ব্যর্থ হয় তবে কেন এটি ব্যর্থ হয়েছিল তা আমাদের জানার উপায় নেই । আপনি দেখতে পাচ্ছেন, stringstreamযদি আপনি দৃust়তা এবং স্পষ্ট ত্রুটি পরিচালনা করতে চান তবে অনেকগুলি পছন্দ করতে পারা যায়।

এটি আমার দ্বিতীয় পরামর্শের দিকে নিয়ে যায়: এর lexical_castজন্য বুস্টের কোনও ব্যবহার করবেন নাlexical_castডকুমেন্টেশনটি কী বলে তা বিবেচনা করুন :

যেখানে রূপান্তরগুলির উপর একটি উচ্চতর ডিগ্রি নিয়ন্ত্রণ প্রয়োজন, স্ট্যান্ড স্ট্রিংস্ট্রিম এবং স্ট্যান্ড :: ডাব্লুস্ট্রিংস্ট্রিম আরও উপযুক্ত পথ সরবরাহ করে। যেখানে অ-স্ট্রিম-ভিত্তিক রূপান্তরগুলি প্রয়োজন, লেক্সিক্যাল_কাস্ট কাজের জন্য ভুল সরঞ্জাম এবং এই জাতীয় পরিস্থিতিতে special

কি?? আমরা ইতিমধ্যে দেখেছি যে stringstreamনিয়ন্ত্রণের একটি নিম্ন স্তরের নিয়ন্ত্রণ রয়েছে, এবং এখনও আপনার "নিয়ন্ত্রণের উচ্চ স্তরের" প্রয়োজন হলে stringstreamএটি ব্যবহার করা উচিত বলে মনে করে lexical_cast। এছাড়াও, কারণ lexical_castকেবল একটি মোড়কের চারপাশে stringstream, এটি একই সমস্যাগুলি ভোগ stringstreamকরে: একাধিক সংখ্যা ঘাঁটি এবং দুর্বল ত্রুটি পরিচালনার জন্য দুর্বল সমর্থন।

সবচেয়ে ভালো সমাধান

ভাগ্যক্রমে, ইতিমধ্যে কেউ উপরের সমস্ত সমস্যার সমাধান করেছেন। সি স্ট্যান্ডার্ড লাইব্রেরিতে strtolএবং পরিবার রয়েছে যার মধ্যে এই সমস্যাগুলির কোনওটিই নেই।

enum STR2INT_ERROR { SUCCESS, OVERFLOW, UNDERFLOW, INCONVERTIBLE };

STR2INT_ERROR str2int (int &i, char const *s, int base = 0)
{
    char *end;
    long  l;
    errno = 0;
    l = strtol(s, &end, base);
    if ((errno == ERANGE && l == LONG_MAX) || l > INT_MAX) {
        return OVERFLOW;
    }
    if ((errno == ERANGE && l == LONG_MIN) || l < INT_MIN) {
        return UNDERFLOW;
    }
    if (*s == '\0' || *end != '\0') {
        return INCONVERTIBLE;
    }
    i = l;
    return SUCCESS;
}

এমন কোনও কিছুর জন্য অত্যন্ত সহজ যা সমস্ত ত্রুটির কেসগুলি পরিচালনা করে এবং 2 থেকে 36 পর্যন্ত যে কোনও সংখ্যা বেসকে সমর্থন করে। যদি baseশূন্য হয় (ডিফল্ট) এটি কোনও বেস থেকে রূপান্তর করার চেষ্টা করবে। অথবা কলার তৃতীয় যুক্তি সরবরাহ করতে পারে এবং নির্দিষ্ট করে যে রূপান্তরটি কেবলমাত্র একটি নির্দিষ্ট বেসের জন্য চেষ্টা করা উচিত। এটি শক্তিশালী এবং সর্বনিম্ন পরিশ্রমের সাথে সমস্ত ত্রুটি পরিচালনা করে।

পছন্দ করার অন্যান্য কারণ strtol(এবং পরিবার):

  • এটি রানটাইমের আরও ভাল পারফরম্যান্স প্রদর্শন করে
  • এটি কম কম্পাইল-টাইম ওভারহেড উপস্থাপন করে (অন্যরা শিরোনাম থেকে প্রায় 20 গুণ বেশি এসএলওসি টান দেয়)
  • এটি ক্ষুদ্রতম কোড আকারে ফলাফল

অন্য কোনও পদ্ধতি ব্যবহারের জন্য একেবারে ভাল কারণ নেই।


22
@ জামেসডুন: পসিক্সের strtolথ্রেড-সেফ থাকা দরকার। পসিক্সেরও errnoথ্রেড-লোকাল স্টোরেজ ব্যবহার করা দরকার । এমনকি নন-পসিক্স সিস্টেমে, errnoমাল্টিথ্রেডেড সিস্টেমে প্রায় সমস্ত বাস্তবায়ন থ্রেড-লোকাল স্টোরেজ ব্যবহার করে। সর্বশেষতম সি ++ স্ট্যান্ডার্ডের জন্য errnoপসিক্স অনুগত হওয়া দরকার । সর্বশেষতম সি স্ট্যান্ডার্ডে errnoথ্রেড-লোকাল স্টোরেজ থাকাও দরকার । এমনকি উইন্ডোজেও, যা অবশ্যই পসিক্সের অনুগত নয়, errnoএটি থ্রেড-সেফ এবং এক্সটেনশনের মাধ্যমেও তাই strtol
ড্যান মোল্ডিং

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

8
এটি সি ++ এর মধ্যে অনুপযুক্ত সি কোডিং। স্ট্যান্ডার্ড লাইব্রেরিতে এর std::stolজন্য রয়েছে , যা সঠিকভাবে প্রত্যাবর্তনের চেয়ে ব্যতিক্রম ছুঁড়ে ফেলবে।
fuzzyTew

22
@FuzzyTew আমি এই উত্তরটি আগে লিখলাম std::stolএমনকি সি ++ ভাষাতে যুক্ত করা হয়েছিল। এটি বলেছিল, আমি এটি "সি সি ++ এর মধ্যে সি কোডিং" বলা ঠিক না বলে মনে করি না। এটি নির্বোধভাবে বলা যায় যে std::strtolসি কোডিং যখন এটি স্পষ্টভাবে সি ++ ভাষার অংশ হয়। আমার উত্তরটি সি ++ তে পুরোপুরি প্রয়োগ হয়েছিল যখন এটি লেখা হয়েছিল এবং এটি এখনও নতুনটির সাথে প্রযোজ্য std::stol। ব্যতিক্রমগুলি ডেকে আনে এমন ফাংশনগুলি কল করা প্রতিটি প্রোগ্রামিং পরিস্থিতিতে সর্বদা সেরা না।
ড্যান মোল্ডিং

9
@ ফাজিটাইউ: ডিস্কের জায়গার বাইরে চলে যাওয়া একটি ব্যতিক্রমী শর্ত। কম্পিউটার উত্পাদিত ম্যাল ফর্ম্যাট ডেটা ফাইলগুলি একটি ব্যতিক্রমী শর্ত। তবে ব্যবহারকারী ইনপুটটিতে টাইপগুলি ব্যতিক্রমী নয়। পার্সিং পদ্ধতির সাথে থাকা ভাল যা স্বাভাবিক, অ-ব্যতিক্রমী পার্সিং ব্যর্থতাগুলি পরিচালনা করতে সক্ষম।
বেন ভয়েগট

67

এটি আটোয়ার চেয়ে নিরাপদ সি ()

const char* str = "123";
int i;

if(sscanf(str, "%d", &i)  == EOF )
{
   /* error */
}

স্ট্যান্ডার্ড স্ট্রিমস্ট্রিম সহ সি ++ : (ধন্যবাদ সিএমএস )

int str2int (const string &str) {
  stringstream ss(str);
  int num;
  if((ss >> num).fail())
  { 
      //ERROR 
  }
  return num;
}

সঙ্গে বুস্ট গ্রন্থাগার: (ধন্যবাদ জে )

#include <boost/lexical_cast.hpp>
#include <string>

try
{
    std::string str = "123";
    int number = boost::lexical_cast< int >( str );
}
catch( const boost::bad_lexical_cast & )
{
    // Error
}

সম্পাদনা: স্ট্রিংস্ট্রিম সংস্করণটি ঠিক করা হয়েছে যাতে এটি ত্রুটিগুলি পরিচালনা করে। (মূল পোস্টে সিএমএস এবং জেকের মন্তব্যে ধন্যবাদ)


1
দয়া করে আপনার স্ট্রিং স্ট্রিম সংস্করণটি আপডেট করে স্ট্রিং স্ট্রিমের জন্য একটি চেক অন্তর্ভুক্ত করুন: ব্যর্থ () (প্রশ্নকর্তা "শক্তিশালী এবং পরিষ্কার ত্রুটি পরিচালনা" এর অনুরোধ হিসাবে)
জে কে।

2
আপনার স্ট্রিং স্ট্রিম সংস্করণ কোনও অভিযোগ না করে "10haha" এর মতো জিনিস গ্রহণ করবে
জোহানেস স্কাউব - lit

3
(! (SS >> NUM) .fail () && (SS >> WS) .eof ()) এটি থেকে ((SS >> NUM) .fail ()) আপনি lexical_cast মত একই হ্যান্ডলিং চান পরিবর্তন
জোহানেস স্কাউব - লিটব

3
স্ট্যান্ডার্ড স্ট্রিম স্ট্রিম স্ট্যান্ডার্ড পদ্ধতি সহ সি ++ .fail () চেক দিয়ে এমনকি "12-সামস্ট্রিং" এর মতো স্ট্রিংয়ের জন্য কাজ করে না।
ক্যাপ্টনসজেজ

সি ++ 11 এর এখনকার জন্য স্ট্যান্ডার্ড দ্রুত ফাংশন অন্তর্ভুক্ত রয়েছে
fuzzyTew

21

ভাল 'পুরানো সি উপায় এখনও কাজ করে। আমি স্ট্র্টল বা স্ট্র্টল সুপারিশ করি। রিটার্নের স্থিতি এবং 'এন্ডপ্রিটার' এর মধ্যে আপনি ভাল ডায়াগনস্টিক আউটপুট দিতে পারেন। এটি একাধিক ঘাঁটিও সুন্দরভাবে পরিচালনা করে।


4
ওহ দয়া করে সি ++ প্রোগ্রামিং করার সময় এই পুরানো সি স্টাফ ব্যবহার করবেন না। সি ++ এ আরও ভাল / সহজ / ক্লিনার / আরও আধুনিক / নিরাপদ উপায় আছে!
জে কে।

27
লোকেরা যখন সমস্যা সমাধানের "আরও আধুনিক" উপায় সম্পর্কে উদ্বিগ্ন হয় তখন মজার বিষয়।
জে মিলার

@ জেসন, আইএমও শক্তিশালী ধরণের সুরক্ষা এবং ত্রুটি পরিচালনার বিষয়টি সি এর তুলনায় আরও আধুনিক ধারণা
ইউজিন ইয়োকোটা

6
আমি অন্য উত্তরগুলির দিকে নজর রেখেছি এবং এ পর্যন্ত কিছুই স্পষ্টতই ভাল / সহজ / ক্লিনার বা নিরাপদ নয়। পোস্টারে বলা হয়েছিল তার একটি চর ছিল *। এটি আপনাকে যে পরিমাণ সুরক্ষা পেতে চলেছে তা সীমিত করে :)
ক্রিস আরগুইন

21

আপনি বুস্টlexical_cast ব্যবহার করতে পারেন , এটি এটি আরও জেনেরিক ইন্টারফেসে আবৃত করে। ব্যর্থতার দিকে lexical_cast<Target>(Source)ছুড়ে ফেলেbad_lexical_cast


12
বুস্ট লেক্সিক্যাল_কাস্ট অত্যন্ত ধীর এবং বেদনাদায়কভাবে অদক্ষ।

3
@Matthieu আপডেট অনুমোদন উন্নত কার্য সম্পাদনার বেশ একটু করেছেন: boost.org/doc/libs/1_49_0/doc/html/boost_lexical_cast/... (আরো দেখুন stackoverflow.com/questions/1250795/... )
উড়ে

16

আপনি সি ++ স্ট্যান্ডার্ড লাইব্রেরি থেকে স্ট্রিংস্ট্রিম ব্যবহার করতে পারেন:

stringstream ss(str);
int x;
ss >> x;

if(ss) { // <-- error handling
  // use x
} else {
  // not a number
}

পূর্ণসংখ্যা পড়ার চেষ্টা করার সময় অ-অঙ্কের সম্মুখীন হলে স্ট্রিমের স্টেটটি ব্যর্থ হয়ে সেট করা হবে।

দেখুন স্ট্রিম ফাঁদ এবং C ++ errorhandling এর ফাঁদ স্ট্রিম জন্য।


2
সি ++ স্ট্রিং স্ট্রিম পদ্ধতি "12-সামস্ট্রিং" এর মতো স্ট্রিং এমনকি 'স্ট্রিম স্টেট' চেকের সাথেও কাজ করে না।
ক্যাপ্টনসজেজ

10

আপনি স্ট্রিংস্ট্রিম ব্যবহার করতে পারেন

int str2int (const string &str) {
  stringstream ss(str);
  int num;
  ss >> num;
  return num;
}

4
তবে এটি কোনও ত্রুটি পরিচালনা করে না। ব্যর্থতার জন্য আপনাকে স্ট্রিমটি পরীক্ষা করতে হবে।
জে কে।

1
ডানদিকে আপনাকে স্ট্রিমটি পরীক্ষা করতে হবে ((এসএস >> নাম্বার)। ফেইল ()) {// ইআরআর}
সিএমএস

2
সি ++ স্ট্রিং স্ট্রিম পদ্ধতি "12-সামস্ট্রিং" এর মতো স্ট্রিংয়ের জন্য এমনকি 'স্ট্রিম স্টেট' চেকের সাথে কাজ করে না
ক্যাপ্টনসজ

8

আমি মনে করি এই তিনটি লিঙ্কের সমষ্টি:

স্ট্রিংস্ট্রিম এবং লেজিক্যাল_কাস্ট সলিউশনগুলির প্রায় একইরকম লেসিকাল কাস্ট স্ট্রিংস্ট্রিম ব্যবহার করছে।

লেক্সিকাল কাস্টের কিছু বিশেষীকরণ বিভিন্ন পদ্ধতির ব্যবহারের জন্য বিশদ জানতে http://www.boost.org/doc/libs/re कृपया/boost/lexical_cast.hpp দেখুন । পূর্ণসংখ্যা এবং ফ্লোটগুলি এখন স্ট্রিং রূপান্তরকরণের জন্য বিশেষীকরণ করা হয়।

কেউ তার নিজের প্রয়োজনের জন্য লেক্সিক্যাল_কাস্ট বিশেষায়িত করতে এবং এটিকে দ্রুত তৈরি করতে পারে। এটি চূড়ান্ত সমাধান হবে সমস্ত পক্ষকে সন্তুষ্ট করে, পরিষ্কার এবং সহজ।

ইতিমধ্যে উল্লিখিত নিবন্ধগুলি পূর্ণসংখ্যার <-> স্ট্রিংকে রূপান্তর করার বিভিন্ন পদ্ধতির মধ্যে তুলনা দেখায়। নিম্নলিখিত পদ্ধতিগুলি বোঝায়: পুরানো সি-ওয়ে, স্পিরিটি.কর্মা, ফাস্টফর্ম্যাট, সহজ সরল লুপ।

লেক্সিক্যাল_কাস্ট কিছু ক্ষেত্রে যেমন ইন্ট টু স্ট্রিং রূপান্তরটির জন্য ঠিক আছে।

লেক্সিকাল কাস্ট ব্যবহার করে স্ট্রিংকে ইনটে রূপান্তর করা ভাল ধারণা নয় কারণ এটি ব্যবহৃত প্ল্যাটফর্ম / সংকলকটির উপর নির্ভর করে আটয়ের চেয়ে 10-40 গুণ কম ধীর।

বুস্ট.স্প্রিট.কর্মা পূর্ণসংখ্যাকে স্ট্রিংয়ে রূপান্তর করার জন্য দ্রুততম গ্রন্থাগার বলে মনে হচ্ছে।

ex.: generate(ptr_char, int_, integer_number);

এবং উপরে উল্লিখিত নিবন্ধের মৌলিক সরল লুপটি স্ট্রিংকে ইনটিতে রূপান্তরিত করার দ্রুততম উপায়, সম্ভবত নিরাপদ নয়, স্ট্রটল () নিরাপদ সমাধানের মতো বলে মনে হচ্ছে

int naive_char_2_int(const char *p) {
    int x = 0;
    bool neg = false;
    if (*p == '-') {
        neg = true;
        ++p;
    }
    while (*p >= '0' && *p <= '9') {
        x = (x*10) + (*p - '0');
        ++p;
    }
    if (neg) {
        x = -x;
    }
    return x;
}

7

সি ++ স্ট্রিং টুলকিট লাইব্রেরি (StrTk) নিম্নলিখিত সমাধান আছে:

static const std::size_t digit_table_symbol_count = 256;
static const unsigned char digit_table[digit_table_symbol_count] = {
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xFF - 0x07
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x08 - 0x0F
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x10 - 0x17
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x18 - 0x1F
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x20 - 0x27
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x28 - 0x2F
   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 0x30 - 0x37
   0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x38 - 0x3F
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x40 - 0x47
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x48 - 0x4F
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x50 - 0x57
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x58 - 0x5F
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x60 - 0x67
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x68 - 0x6F
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x70 - 0x77
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x78 - 0x7F
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x80 - 0x87
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x88 - 0x8F
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x90 - 0x97
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0x98 - 0x9F
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xA0 - 0xA7
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xA8 - 0xAF
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xB0 - 0xB7
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xB8 - 0xBF
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xC0 - 0xC7
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xC8 - 0xCF
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xD0 - 0xD7
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xD8 - 0xDF
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xE0 - 0xE7
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xE8 - 0xEF
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // 0xF0 - 0xF7
   0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF  // 0xF8 - 0xFF
 };

template<typename InputIterator, typename T>
inline bool string_to_signed_type_converter_impl_itr(InputIterator begin, InputIterator end, T& v)
{
   if (0 == std::distance(begin,end))
      return false;
   v = 0;
   InputIterator it = begin;
   bool negative = false;
   if ('+' == *it)
      ++it;
   else if ('-' == *it)
   {
      ++it;
      negative = true;
   }
   if (end == it)
      return false;
   while(end != it)
   {
      const T digit = static_cast<T>(digit_table[static_cast<unsigned int>(*it++)]);
      if (0xFF == digit)
         return false;
      v = (10 * v) + digit;
   }
   if (negative)
      v *= -1;
   return true;
}

ইনপুটআইটিরেটর স্বাক্ষরযুক্ত চর *, চর * বা স্টাডি :: স্ট্রিং পুনরাবৃত্তকারীগুলির হতে পারে এবং টি প্রত্যাশিত একটি স্বাক্ষরপ্রাপ্ত, যেমন স্বাক্ষরযুক্ত ইন্ট, ইনট বা দীর্ঘ


1
সতর্কতা এই বাস্তবায়নটি দেখতে দুর্দান্ত দেখাচ্ছে, তবে আমি যতটা বলতে পারি ওভারফ্লোগুলি পরিচালনা করে না।
ভিনি ফ্যালকো

2
কোড ওভারফ্লো পরিচালনা করে না। v = (10 * v) + digit;এর পাঠ্যের মান সহ স্ট্রিং ইনপুটটি অযথা ওভারফ্লো হয় INT_MIN। টেবিলটি প্রশ্নোত্তর মূল্য বনাম কেবলdigit >= '0' && digit <= '9'
chux -

6

আপনি সি ++ 11 থেকে থাকে, তাহলে উপযুক্ত সমাধান আজকাল সি ++ এ রূপান্তর ফাংশন পূর্ণসংখ্যা হয় <string>: stoi, stol, stoul, stoll, stoull। ভুল ইনপুট দেওয়া হলে তারা উপযুক্ত ব্যতিক্রম ছুঁড়ে দেয় এবং দ্রুত এবং ছোট ব্যবহার করেstrto* ফণীর নীচে ফাংশন ।

আপনি যদি সি ++ এর পূর্ববর্তী পুনর্বিবেচনায় আটকে থাকেন তবে আপনার প্রয়োগে এই ফাংশনগুলি নকল করা আপনার পক্ষে ফরওয়ার্ডযোগ্য would


6

সি ++ 17 থেকে আপনি এখানে নথির মতো শিরোনাম std::from_charsথেকে ব্যবহার করতে পারেন ।<charconv>

উদাহরণ স্বরূপ:

#include <iostream>
#include <charconv>
#include <array>

int main()
{
    char const * str = "42";
    int value = 0;

    std::from_chars_result result = std::from_chars(std::begin(str), std::end(str), value);

    if(result.error == std::errc::invalid_argument)
    {
      std::cout << "Error, invalid format";
    }
    else if(result.error == std::errc::result_out_of_range)
    {
      std::cout << "Error, value too big for int range";
    }
    else
    {
      std::cout << "Success: " << result;
    }
}

বোনাস হিসাবে এটি হেক্সাডেসিমালের মতো অন্যান্য ঘাঁটিগুলিও পরিচালনা করতে পারে।


3

আমি ড্যান মোল্ডিংয়ের উত্তরটি পছন্দ করি , আমি এটিতে কিছুটা সি ++ স্টাইল যুক্ত করব:

#include <cstdlib>
#include <cerrno>
#include <climits>
#include <stdexcept>

int to_int(const std::string &s, int base = 0)
{
    char *end;
    errno = 0;
    long result = std::strtol(s.c_str(), &end, base);
    if (errno == ERANGE || result > INT_MAX || result < INT_MIN)
        throw std::out_of_range("toint: string is out of range");
    if (s.length() == 0 || *end != '\0')
        throw std::invalid_argument("toint: invalid string");
    return result;
}

এটি অন্তর্নিহিত রূপান্তর মাধ্যমে std :: স্ট্রিং এবং কনস্ট চর * উভয়ের পক্ষে কাজ করে। এটি বেস রূপান্তরকরণের জন্যও কার্যকর, যেমন সমস্ত to_int("0x7b")এবং to_int("0173")এবং to_int("01111011", 2)এবং to_int("0000007B", 16)এবং to_int("11120", 3)এবং to_int("3L", 34);123 ফেরত আসবে।

ভিন্ন std::stoiএটা প্রাক সি ++ 11 কাজ করে। এছাড়াও বিপরীত std::stoi, boost::lexical_castএবংstringstream এটি "123hohoho" এর মতো অদ্ভুত স্ট্রিংগুলির ব্যতিক্রম ছুঁড়ে।

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

এই জাতীয় অনুষ্ঠানটি এসটিএলের অংশ হতে পারে ...


2

আমি স্ট্রিংকে ইনটে রূপান্তর করার তিনটি উপায় জানি:

হয় স্টোই (স্ট্রিং টু ইনট) ফাংশনটি ব্যবহার করুন বা স্ট্রিংস্ট্রিমের সাথে চলুন, পৃথক রূপান্তরকরণের তৃতীয় উপায়, কোডটি নীচে রয়েছে:

1 ম পদ্ধতি

std::string s1 = "4533";
std::string s2 = "3.010101";
std::string s3 = "31337 with some string";

int myint1 = std::stoi(s1);
int myint2 = std::stoi(s2);
int myint3 = std::stoi(s3);

std::cout <<  s1 <<"=" << myint1 << '\n';
std::cout <<  s2 <<"=" << myint2 << '\n';
std::cout <<  s3 <<"=" << myint3 << '\n';

২ য় পদ্ধতি

#include <string.h>
#include <sstream>
#include <iostream>
#include <cstring>
using namespace std;


int StringToInteger(string NumberAsString)
{
    int NumberAsInteger;
    stringstream ss;
    ss << NumberAsString;
    ss >> NumberAsInteger;
    return NumberAsInteger;
}
int main()
{
    string NumberAsString;
    cin >> NumberAsString;
    cout << StringToInteger(NumberAsString) << endl;
    return 0;
} 

তৃতীয় পদ্ধতি - তবে পৃথক রূপান্তরকরণের জন্য নয়

std::string str4 = "453";
int i = 0, in=0; // 453 as on
for ( i = 0; i < str4.length(); i++)
{

    in = str4[i];
    cout <<in-48 ;

}

1

আমি ড্যানের উত্তর পছন্দ করি , ব্যতিক্রমগুলি এড়ানোর কারণে sp এম্বেড থাকা সিস্টেম বিকাশ এবং অন্যান্য নিম্ন স্তরের সিস্টেম বিকাশের জন্য, উপযুক্ত ব্যতিক্রম কাঠামো উপলব্ধ নাও থাকতে পারে।

একটি বৈধ স্ট্রিংয়ের পরে সাদা-স্পেসের জন্য একটি চেক যুক্ত করা হয়েছে ... এই তিনটি লাইনের

    while (isspace(*end)) {
        end++;
    }


ত্রুটি পার্সিংয়ের জন্য একটি চেক যোগ করা হয়েছে।

    if ((errno != 0) || (s == end)) {
        return INCONVERTIBLE;
    }


এখানে সম্পূর্ণ ফাংশন ..

#include <cstdlib>
#include <cerrno>
#include <climits>
#include <stdexcept>

enum STR2INT_ERROR { SUCCESS, OVERFLOW, UNDERFLOW, INCONVERTIBLE };

STR2INT_ERROR str2long (long &l, char const *s, int base = 0)
{
    char *end = (char *)s;
    errno = 0;

    l = strtol(s, &end, base);

    if ((errno == ERANGE) && (l == LONG_MAX)) {
        return OVERFLOW;
    }
    if ((errno == ERANGE) && (l == LONG_MIN)) {
        return UNDERFLOW;
    }
    if ((errno != 0) || (s == end)) {
        return INCONVERTIBLE;
    }    
    while (isspace((unsigned char)*end)) {
        end++;
    }

    if (*s == '\0' || *end != '\0') {
        return INCONVERTIBLE;
    }

    return SUCCESS;
}

@chux আপনার উল্লিখিত উদ্বেগগুলির যত্ন নিতে কোড যুক্ত করেছে।
পেলুচাইড

1) এখনও ইনপুট মত ত্রুটি সনাক্ত করতে ব্যর্থ " "। কোনও রূপান্তর ঘটে না তখন strtol()সেট করতে নির্দিষ্ট করা হয় না errnoif (s == end) return INCONVERTIBLE; কোনও রূপান্তর সনাক্ত করতে ব্যবহার করা ভাল । এবং তারপরে 2 এ if (*s == '\0' || *end != '\0')সরলীকরণ করতে পারে এবং কোনও উদ্দেশ্য কার্যকর করতে পারে - এগুলি কখনই সত্য হয় না। if (*end)|| l > LONG_MAX|| l < LONG_MIN
chux -

@chux একটি ম্যাক-এ, ত্রুটিগুলি পার্সিংয়ের জন্য এরনো সেট করা হয়েছে, তবে লিনাক্সে এর্ন সেট করা নেই। এটি সনাক্ত করতে "শেষ" পয়েন্টারের উপর নির্ভর করতে কোডটি পরিবর্তন করা হয়েছে।
pellucide

0

আপনি এই সংজ্ঞায়িত পদ্ধতিটি ব্যবহার করতে পারেন।

#define toInt(x) {atoi(x.c_str())};

এবং যদি আপনি স্ট্রিং থেকে একটি পূর্ণসংখ্যায় রূপান্তর করতে চান তবে আপনি কেবল নিম্নলিখিতটি করবেন।

int main()
{
string test = "46", test2 = "56";
int a = toInt(test);
int b = toInt(test2);
cout<<a+b<<endl;
}

আউটপুট হবে 102।


4
idk। আশেপাশে একটি সংজ্ঞায়িত ম্যাক্রো রচনা atoiগ্রহণযোগ্য যেমন উত্তরগুলির আলোকে "সি ++ উপায়" বলে মনে হচ্ছে না std::stoi()
ইউজিন ইয়োকোটা

পূর্বনির্ধারিত পদ্ধতিগুলি ব্যবহার করে আমি এটি আরও মজাদার মনে করি: পি
বরিস

0

আমি জানি এটি একটি পুরানো প্রশ্ন, তবে আমি এটি বহুবার এসে পৌঁছেছি এবং আজ পর্যন্ত, নিম্নলিখিত বৈশিষ্ট্যগুলির সাথে একটি সুন্দর টেম্পলেটযুক্ত সমাধান এখনও খুঁজে পাইনি:

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

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

উপভোগ করুন; আশা করি কেউ এটি দরকারী বলে মনে করেন।

#include <cstdlib>
#include <cerrno>
#include <limits>
#include <stdexcept>
#include <sstream>

static const int DefaultBase = 10;

template<typename T>
static inline T CstrtoxllWrapper(const char *str, int base = DefaultBase)
{
    while (isspace(*str)) str++; // remove leading spaces; verify there's data
    if (*str == '\0') { throw std::invalid_argument("str; no data"); } // nothing to convert

    // NOTE:  for some reason strtoull allows a negative sign, we don't; if
    //          converting to an unsigned then it must always be positive!
    if (!std::numeric_limits<T>::is_signed && *str == '-')
    { throw std::invalid_argument("str; negative"); }

    // reset errno and call fn (either strtoll or strtoull)
    errno = 0;
    char *ePtr;
    T tmp = std::numeric_limits<T>::is_signed ? strtoll(str, &ePtr, base)
                                              : strtoull(str, &ePtr, base);

    // check for any C errors -- note these are range errors on T, which may
    //   still be out of the range of the actual type we're using; the caller
    //   may need to perform additional range checks.
    if (errno != 0) 
    {
            if (errno == ERANGE) { throw std::range_error("str; out of range"); }
            else if (errno == EINVAL) { throw std::invalid_argument("str; EINVAL"); }
            else { throw std::invalid_argument("str; unknown errno"); }
    }

    // verify everything converted -- extraneous spaces are allowed
    if (ePtr != NULL)
    {
            while (isspace(*ePtr)) ePtr++;
            if (*ePtr != '\0') { throw std::invalid_argument("str; bad data"); }
    }

    return tmp;
}

template<typename T>
T StringToSigned(const char *str, int base = DefaultBase)
{
    static const long long max = std::numeric_limits<T>::max();
    static const long long min = std::numeric_limits<T>::min();

    long long tmp = CstrtoxllWrapper<typeof(tmp)>(str, base); // use largest type

    // final range check -- only needed if not long long type; a smart compiler
    //   should optimize this whole thing out
    if (sizeof(T) == sizeof(tmp)) { return tmp; }

    if (tmp < min || tmp > max)
    {
            std::ostringstream err;
            err << "str; value " << tmp << " out of " << sizeof(T) * 8
                << "-bit signed range (";
            if (sizeof(T) != 1) err << min << ".." << max;
            else err << (int) min << ".." << (int) max;  // don't print garbage chars
            err << ")";
            throw std::range_error(err.str());
    }

    return tmp;
}

template<typename T>
T StringToUnsigned(const char *str, int base = DefaultBase)
{
    static const unsigned long long max = std::numeric_limits<T>::max();

    unsigned long long tmp = CstrtoxllWrapper<typeof(tmp)>(str, base); // use largest type

    // final range check -- only needed if not long long type; a smart compiler
    //   should optimize this whole thing out
    if (sizeof(T) == sizeof(tmp)) { return tmp; }

    if (tmp > max)
    {
            std::ostringstream err;
            err << "str; value " << tmp << " out of " << sizeof(T) * 8
                << "-bit unsigned range (0..";
            if (sizeof(T) != 1) err << max;
            else err << (int) max;  // don't print garbage chars
            err << ")";
            throw std::range_error(err.str());
    }

    return tmp;
}

template<typename T>
inline T
StringToDecimal(const char *str, int base = DefaultBase)
{
    return std::numeric_limits<T>::is_signed ? StringToSigned<T>(str, base)
                                             : StringToUnsigned<T>(str, base);
}

template<typename T>
inline T
StringToDecimal(T &out_convertedVal, const char *str, int base = DefaultBase)
{
    return out_convertedVal = StringToDecimal<T>(str, base);
}

/*============================== [ Test Strap ] ==============================*/ 

#include <inttypes.h>
#include <iostream>

static bool _g_anyFailed = false;

template<typename T>
void TestIt(const char *tName,
            const char *s, int base,
            bool successExpected = false, T expectedValue = 0)
{
    #define FAIL(s) { _g_anyFailed = true; std::cout << s; }

    T x;
    std::cout << "converting<" << tName << ">b:" << base << " [" << s << "]";
    try
    {
            StringToDecimal<T>(x, s, base);
            // get here on success only
            if (!successExpected)
            {
                    FAIL(" -- TEST FAILED; SUCCESS NOT EXPECTED!" << std::endl);
            }
            else
            {
                    std::cout << " -> ";
                    if (sizeof(T) != 1) std::cout << x;
                    else std::cout << (int) x;  // don't print garbage chars
                    if (x != expectedValue)
                    {
                            FAIL("; FAILED (expected value:" << expectedValue << ")!");
                    }
                    std::cout << std::endl;
            }
    }
    catch (std::exception &e)
    {
            if (successExpected)
            {
                    FAIL(   " -- TEST FAILED; EXPECTED SUCCESS!"
                         << " (got:" << e.what() << ")" << std::endl);
            }
            else
            {
                    std::cout << "; expected exception encounterd: [" << e.what() << "]" << std::endl;
            }
    }
}

#define TEST(t, s, ...) \
    TestIt<t>(#t, s, __VA_ARGS__);

int main()
{
    std::cout << "============ variable base tests ============" << std::endl;
    TEST(int, "-0xF", 0, true, -0xF);
    TEST(int, "+0xF", 0, true, 0xF);
    TEST(int, "0xF", 0, true, 0xF);
    TEST(int, "-010", 0, true, -010);
    TEST(int, "+010", 0, true, 010);
    TEST(int, "010", 0, true, 010);
    TEST(int, "-10", 0, true, -10);
    TEST(int, "+10", 0, true, 10);
    TEST(int, "10", 0, true, 10);

    std::cout << "============ base-10 tests ============" << std::endl;
    TEST(int, "-010", 10, true, -10);
    TEST(int, "+010", 10, true, 10);
    TEST(int, "010", 10, true, 10);
    TEST(int, "-10", 10, true, -10);
    TEST(int, "+10", 10, true, 10);
    TEST(int, "10", 10, true, 10);
    TEST(int, "00010", 10, true, 10);

    std::cout << "============ base-8 tests ============" << std::endl;
    TEST(int, "777", 8, true, 0777);
    TEST(int, "-0111 ", 8, true, -0111);
    TEST(int, "+0010 ", 8, true, 010);

    std::cout << "============ base-16 tests ============" << std::endl;
    TEST(int, "DEAD", 16, true, 0xDEAD);
    TEST(int, "-BEEF", 16, true, -0xBEEF);
    TEST(int, "+C30", 16, true, 0xC30);

    std::cout << "============ base-2 tests ============" << std::endl;
    TEST(int, "-10011001", 2, true, -153);
    TEST(int, "10011001", 2, true, 153);

    std::cout << "============ irregular base tests ============" << std::endl;
    TEST(int, "Z", 36, true, 35);
    TEST(int, "ZZTOP", 36, true, 60457993);
    TEST(int, "G", 17, true, 16);
    TEST(int, "H", 17);

    std::cout << "============ space deliminated tests ============" << std::endl;
    TEST(int, "1337    ", 10, true, 1337);
    TEST(int, "   FEAD", 16, true, 0xFEAD);
    TEST(int, "   0711   ", 0, true, 0711);

    std::cout << "============ bad data tests ============" << std::endl;
    TEST(int, "FEAD", 10);
    TEST(int, "1234 asdfklj", 10);
    TEST(int, "-0xF", 10);
    TEST(int, "+0xF", 10);
    TEST(int, "0xF", 10);
    TEST(int, "-F", 10);
    TEST(int, "+F", 10);
    TEST(int, "12.4", 10);
    TEST(int, "ABG", 16);
    TEST(int, "10011002", 2);

    std::cout << "============ int8_t range tests ============" << std::endl;
    TEST(int8_t, "7F", 16, true, std::numeric_limits<int8_t>::max());
    TEST(int8_t, "80", 16);
    TEST(int8_t, "-80", 16, true, std::numeric_limits<int8_t>::min());
    TEST(int8_t, "-81", 16);
    TEST(int8_t, "FF", 16);
    TEST(int8_t, "100", 16);

    std::cout << "============ uint8_t range tests ============" << std::endl;
    TEST(uint8_t, "7F", 16, true, std::numeric_limits<int8_t>::max());
    TEST(uint8_t, "80", 16, true, std::numeric_limits<int8_t>::max()+1);
    TEST(uint8_t, "-80", 16);
    TEST(uint8_t, "-81", 16);
    TEST(uint8_t, "FF", 16, true, std::numeric_limits<uint8_t>::max());
    TEST(uint8_t, "100", 16);

    std::cout << "============ int16_t range tests ============" << std::endl;
    TEST(int16_t, "7FFF", 16, true, std::numeric_limits<int16_t>::max());
    TEST(int16_t, "8000", 16);
    TEST(int16_t, "-8000", 16, true, std::numeric_limits<int16_t>::min());
    TEST(int16_t, "-8001", 16);
    TEST(int16_t, "FFFF", 16);
    TEST(int16_t, "10000", 16);

    std::cout << "============ uint16_t range tests ============" << std::endl;
    TEST(uint16_t, "7FFF", 16, true, std::numeric_limits<int16_t>::max());
    TEST(uint16_t, "8000", 16, true, std::numeric_limits<int16_t>::max()+1);
    TEST(uint16_t, "-8000", 16);
    TEST(uint16_t, "-8001", 16);
    TEST(uint16_t, "FFFF", 16, true, std::numeric_limits<uint16_t>::max());
    TEST(uint16_t, "10000", 16);

    std::cout << "============ int32_t range tests ============" << std::endl;
    TEST(int32_t, "7FFFFFFF", 16, true, std::numeric_limits<int32_t>::max());
    TEST(int32_t, "80000000", 16);
    TEST(int32_t, "-80000000", 16, true, std::numeric_limits<int32_t>::min());
    TEST(int32_t, "-80000001", 16);
    TEST(int32_t, "FFFFFFFF", 16);
    TEST(int32_t, "100000000", 16);

    std::cout << "============ uint32_t range tests ============" << std::endl;
    TEST(uint32_t, "7FFFFFFF", 16, true, std::numeric_limits<int32_t>::max());
    TEST(uint32_t, "80000000", 16, true, std::numeric_limits<int32_t>::max()+1);
    TEST(uint32_t, "-80000000", 16);
    TEST(uint32_t, "-80000001", 16);
    TEST(uint32_t, "FFFFFFFF", 16, true, std::numeric_limits<uint32_t>::max());
    TEST(uint32_t, "100000000", 16);

    std::cout << "============ int64_t range tests ============" << std::endl;
    TEST(int64_t, "7FFFFFFFFFFFFFFF", 16, true, std::numeric_limits<int64_t>::max());
    TEST(int64_t, "8000000000000000", 16);
    TEST(int64_t, "-8000000000000000", 16, true, std::numeric_limits<int64_t>::min());
    TEST(int64_t, "-8000000000000001", 16);
    TEST(int64_t, "FFFFFFFFFFFFFFFF", 16);
    TEST(int64_t, "10000000000000000", 16);

    std::cout << "============ uint64_t range tests ============" << std::endl;
    TEST(uint64_t, "7FFFFFFFFFFFFFFF", 16, true, std::numeric_limits<int64_t>::max());
    TEST(uint64_t, "8000000000000000", 16, true, std::numeric_limits<int64_t>::max()+1);
    TEST(uint64_t, "-8000000000000000", 16);
    TEST(uint64_t, "-8000000000000001", 16);
    TEST(uint64_t, "FFFFFFFFFFFFFFFF", 16, true, std::numeric_limits<uint64_t>::max());
    TEST(uint64_t, "10000000000000000", 16);

    std::cout << std::endl << std::endl
              << (_g_anyFailed ? "!! SOME TESTS FAILED !!" : "ALL TESTS PASSED")
              << std::endl;

    return _g_anyFailed;
}

StringToDecimalব্যবহারকারী-ভূমি পদ্ধতি; এটি অত্যধিক লোড হয়েছে যাতে এটি এর মতো হয়:

int a; a = StringToDecimal<int>("100");

অথবা এটা:

int a; StringToDecimal(a, "100");

আমি int টাইপ পুনরাবৃত্তি ঘৃণা করি, তাই পরে পছন্দ। এটি নিশ্চিত করে যে 'ক' এর ধরণের পরিবর্তন হলে খারাপ ফলাফল না পাওয়া যায়। আমি আশা করি সংকলকটি এটির মতো নির্ধারণ করতে পারে:

int a; a = StringToDecimal("100");

... তবে, সি ++ টেম্পলেট রিটার্নের ধরণগুলি হ্রাস করে না, তাই এটি আমার পক্ষে সেরা।

বাস্তবায়ন বেশ সহজ:

CstrtoxllWrapperউভয়কে মোড়ানো strtoullএবং strtoll, টেমপ্লেট টাইপের স্বাক্ষরিত নেসের উপর ভিত্তি করে যা কিছু প্রয়োজন তা কল করা এবং কিছু অতিরিক্ত গ্যারান্টি সরবরাহ করার জন্য (যেমন স্বাক্ষরিত না হলে নেতিবাচক ইনপুটটি অনুমোদিত নয় এবং এটি নিশ্চিত করে যে পুরো স্ট্রিংটি রূপান্তরিত হয়েছিল)।

CstrtoxllWrapperসংকলকটিতে উপলব্ধ বৃহত্তম ধরণের (দীর্ঘ দীর্ঘ / স্বাক্ষরযুক্ত দীর্ঘ দীর্ঘ) ব্যবহার করে StringToSignedএবং এর StringToUnsignedসাথে ব্যবহৃত হয় ; এটি সর্বাধিক রূপান্তর সম্পাদন করতে দেয়। তারপরে, যদি এটি প্রয়োজন হয়, StringToSigned/ StringToUnsignedঅন্তর্নিহিত ধরণের উপর চূড়ান্ত পরিসীমা চেক করে। পরিশেষে, শেষ-পয়েন্ট পদ্ধতি,StringToDecimal সিদ্ধান্ত নেয় যে অন্তর্নিহিত ধরণের স্বাক্ষরিত নেসের উপর ভিত্তি করে স্ট্রিংটো * টেম্পলেট পদ্ধতিগুলির মধ্যে কোনটি কল করতে হবে।

আমি মনে করি সংকলক দ্বারা বেশিরভাগ জাঙ্কটি অপ্টিমাইজ করা যেতে পারে; প্রায় সবই সংকলন-সময় নির্বাহী হওয়া উচিত। এই দিক সম্পর্কে যে কোনও মন্তব্য আমার কাছে আকর্ষণীয় হবে!


"বৃহত্তম ধরণের ব্যবহার করুন" -> এর long longপরিবর্তে কেন intmax_t?
chux - মনিকা পুনরায় ইনস্টল

আপনি চান আত্মবিশ্বাস if (ePtr != str)। আরও, এর isspace((unsigned char) *ePtr)নেতিবাচক মানগুলি সঠিকভাবে পরিচালনা করতে ব্যবহার করুন *ePtr
chux - মনিকা পুনরায় ইনস্টল

-3

সি তে, আপনি ব্যবহার করতে পারেন int atoi (const char * str),

সি-স্ট্রিং স্ট্রাস্ট করে এর সামগ্রীটিকে একটি অবিচ্ছেদ্য সংখ্যা হিসাবে ব্যাখ্যা করে, যা টাইপ ইন্টের মান হিসাবে ফিরে আসে।


2
আমি যেমন atoiপ্রশ্নের সাথে লিঙ্ক করেছি , আমি এটি সম্পর্কে অবহিত। প্রশ্নটি পরিষ্কারভাবে সি সম্পর্কে নয়, সি ++ সম্পর্কে। -1
ইউজিন ইওকোটা
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.