سؤال

لدي بعض الأرقام ذات أطوال مختلفة (مثل 1، 999، 76492، وما إلى ذلك) وأريد تحويلها جميعًا إلى سلاسل ذات طول مشترك (على سبيل المثال، إذا كان الطول 6، فستكون هذه السلاسل:"000001"، "000999"، "076492").

بمعنى آخر، أحتاج إلى إضافة المقدار الصحيح من الأصفار البادئة إلى الرقم.

int n = 999;
string str = some_function(n,6);
//str = '000999'

هل هناك وظيفة مثل هذه في C++؟

هل كانت مفيدة؟

المحلول

وأو باستخدام stringstreams:

#include <sstream>
#include <iomanip>

std::stringstream ss;
ss << std::setw(10) << std::setfill('0') << i;
std::string s = ss.str();

وأنا جمعت المعلومات وجدت على arachnoid.com لأنني أحب type- طريقة آمنة أمام iostreams أكثر. الى جانب ذلك، يمكنك استخدام هذا الرمز بالتساوي على أي تيار الإخراج الأخرى.

نصائح أخرى

char str[7];
snprintf (str, 7, "%06d", n);

snprintf

شيء واحد لك يمكن تريد أن تكون على دراية بالقفل المحتمل الذي قد يحدث عند استخدام stringstream يقترب.في STL التي تأتي مع Visual Studio 2008، على الأقل، هناك العديد من الأقفال التي تم إخراجها وإصدارها حيث يتم استخدام معلومات محلية مختلفة أثناء التنسيق.قد يمثل هذا أو لا يمثل مشكلة بالنسبة لك اعتمادًا على عدد سلاسل الرسائل لديك والتي قد تقوم بتحويل الأرقام إلى سلاسل بشكل متزامن ...

ال sprintf الإصدار لا يتطلب أي أقفال (على الأقل وفقًا لأداة مراقبة القفل التي أقوم بتطويرها حاليًا...) وبالتالي قد يكون "أفضل" للاستخدام في المواقف المتزامنة.

لقد لاحظت هذا فقط لأن أداتي قامت مؤخرًا بإخراج الأقفال "اللغة المحلية" باعتبارها من بين أكثر الأقفال التي يتم التنافس عليها في نظام الخادم الخاص بي؛لقد كان ذلك بمثابة مفاجأة بعض الشيء وقد يدفعني إلى مراجعة النهج الذي كنت أتبعه (أي.العودة نحو sprintf من stringstream)...

وstringstream ستفعل ( كما وأشار xtofl من ). شكل دفعة هو أكثر ملاءمة استبدال لsnprintf.

وهذه الطريقة لا تستخدم تيارات ولا sprintf. بخلاف وجود مشاكل تأمين، والجداول تكبد النفقات العامة الأداء وهو في حقيقة الأمر مبالغة. لتيارات الحمل يأتي من الحاجة لبناء المخزن المؤقت البخار وتيار. لsprintf، والنفقات العامة يأتي من الحاجة إلى تفسير سلسلة التنسيق. يعمل هذا حتى عندما <م> ن هو سلبي أو عند تمثيل سلسلة <م> ن أطول من ليون . هذا هو أسرع حل.

inline string some_function(int n, int len)
{
    string result(len--, '0');
    for (int val=(n<0)?-n:n; len>=0&&val!=0; --len,val/=10)
       result[len]='0'+val%10;
    if (len>=0&&n<0) result[0]='-';
    return result;
}

وهناك طرق عديدة للقيام بذلك. إن أبسط يكون:

int n = 999;
char buffer[256]; sprintf(buffer, "%06d", n);
string str(buffer);

وsprintf هو الطريق C-مثل للقيام بذلك، والذي يعمل أيضا في C ++.

في C ++، وهو مزيج من التنسيق stringstream ودفق إخراج (انظر HTTP: // شبكة الاتصالات العالمية .arachnoid.com / cpptutor / student3.html ) سوف قيام بهذه المهمة.

هذا موضوع قديم، ولكن كما fmt قد يصبح معيارًا، إليك حل إضافي:

#include <fmt/format.h>

int n = 999;

const auto str = fmt::format("{:0>{}}", n, 6);

نلاحظ أن fmt::format("{:0>6}", n) يعمل بشكل جيد على قدم المساواة عندما يكون العرض المطلوب معروفًا في وقت الترجمة.خيار آخر هو الهبوط:

#include <absl/strings/str_format.h>

int n = 999;

const auto str = absl::StrFormat("%0*d", 6, n);

مرة أخرى، abs::StrFormat("%06d", n) ممكن. تنسيق تعزيز أداة أخرى لهذه المشكلة:

#include <boost/format.hpp>

int n = 999;

const auto str = boost::str(boost::format("%06d") % n);

لسوء الحظ، محدد العرض المتغير كوسيطات متسلسلة مع % عامل التشغيل غير مدعوم، وهذا يتطلب إعداد سلسلة التنسيق (على سبيل المثال. const std::string fmt = "%0" + std::to_string(6) + "d";).

من حيث الأداء، يُزعم أن abseil وfmt جذابان للغاية وأسرع من التعزيز.على أية حال، يجب أن تكون الحلول الثلاثة أكثر كفاءة من std::stringstream النهج، وغير ذلك std::*printf الأسرة، فإنهم لا يضحون بالسلامة النوعية.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top